OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [eth/] [mcf52xx/] [mcf5272/] [current/] [src/] [if_mcf5272.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      dev/if_MCF5272_fec.c
4
//
5
//      Ethernet device driver for MCF5272's Fast Ethernet Controller (FEC)
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
 
41
 
42
// Ethernet device driver for Fast Ethernet MCF5272_fec
43
#include <pkgconf/io_eth_drivers.h>
44
 
45
#include <cyg/hal/drv_api.h>
46
#include <cyg/io/eth/netdev.h>
47
#include <cyg/io/eth/eth_drv.h>
48
 
49
#include <cyg/devs/eth/nbuf.h>
50
#include <cyg/devs/eth/if_mcf5272.h>
51
#include <cyg/devs/eth/if_mcf5272_private_data.h>
52
 
53
#include <cyg/infra/cyg_ass.h>
54
#include <sys/param.h>
55
#include <net/if.h>
56
 
57
 
58
/* Function to retrieve the Ethernet address of the device from the device's
59
   database. We declare it weak so that other routines can overide it.
60
   */
61
 
62
externC const void*
63
db_get_eth_address(void) __attribute__ ((weak));
64
 
65
 
66
/*****************************************************************************
67
 
68
     The following  functions  provide  an  interface  directly  to  the
69
ethernet driver for applications that wish to circumvent the IP stack.
70
 
71
     Applications that wish  to take advantage  of this should  override
72
these routine with their own.  Leaving these routines as default  routes
73
all data through the IP stack.
74
 
75
*****************************************************************************/
76
externC int_t
77
eth_rx_pkt_filter(u8_t* pkt, uint_t pkt_len) __attribute__ ((weak));
78
externC void
79
eth_tx_check(struct eth_drv_sg * sg_list, unsigned int sg_len)
80
             __attribute__ ((weak));
81
externC void
82
eth_send_done(unsigned long tag) __attribute__ ((weak));
83
externC int_t
84
eth_send(struct eth_drv_sg * sg_list, unsigned int sg_len, int total_len,
85
         unsigned long tag);
86
 
87
static MCF5272_fec_priv_data_t MCF5272_fec_priv_data;
88
 
89
/* Interrupt strcture and handles. */
90
static cyg_interrupt MCF5272_fec_rx_interrupt;
91
static cyg_interrupt MCF5272_fec_tx_interrupt;
92
 
93
static cyg_handle_t MCF5272_fec_rx_interrupt_handle;
94
static cyg_handle_t MCF5272_fec_tx_interrupt_handle;
95
 
96
 
97
// Interrupt handler
98
static void MCF5272_fec_int(struct eth_drv_sc *sc);
99
static int MCF5272_fec_int_vector(struct eth_drv_sc *sc);
100
 
101
// This DSR handles the ethernet [logical] processing
102
static void MCF5272_fec_deliver(struct eth_drv_sc * sc);
103
static void MCF5272_fec_stop(struct eth_drv_sc *sc);
104
 
105
static void
106
MCF5272_fec_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
107
            int total_len, unsigned long key);
108
 
109
static void
110
MCF5272_fec_common_send(struct eth_drv_sc *sc,
111
                        struct eth_drv_sg *sg_list, int sg_len,
112
                        int total_len,
113
                        unsigned long key,
114
                        tx_key_type_t key_type);
115
 
116
static int
117
MCF5272_fec_isr(cyg_vector_t vector, cyg_addrword_t data,
118
                HAL_SavedRegisters *regs);
119
 
120
 
121
// One-second call back alarm
122
static void one_second_alarm_func(cyg_handle_t alarm, cyg_addrword_t data);
123
 
124
// Retrieve statistics
125
static void MCF5272_get_stats(struct eth_drv_sc *sc, MCF5272_FEC_DIAG* stats);
126
 
127
 
128
ETH_DRV_SC(MCF5272_fec_sc,
129
           &MCF5272_fec_priv_data, // Driver specific data
130
           "eth0",             // Name for this interface
131
           MCF5272_fec_start,
132
           MCF5272_fec_stop,
133
           MCF5272_fec_control,
134
           MCF5272_fec_can_send,
135
           MCF5272_fec_send,
136
           MCF5272_fec_recv,
137
           MCF5272_fec_deliver,
138
           MCF5272_fec_int,
139
           MCF5272_fec_int_vector);
140
 
141
/* Device name */
142
static const char ether_device_name[] =  "MCF5272-eth";
143
 
144
NETDEVTAB_ENTRY(MCF5272_fec_netdev,
145
                ether_device_name,
146
                MCF5272_fec_init,
147
                &MCF5272_fec_sc);
148
 
149
 
150
/*******************************************************************************
151
    db_get_eth_address() - Returns the default Ethernet address.
152
*/
153
const void* db_get_eth_address(void)
154
{
155
 
156
    /*   Just use an obviously invalid address until someone overrides this */
157
    /* routine to provide their own address.                                */
158
 
159
    static const unsigned char enaddr[] =
160
    {
161
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55
162
    };
163
    return  (const void*)enaddr;
164
}
165
/*******************************************************************************
166
 MCF5272_fec_init() - Routine that initializes the FEC.
167
 
168
 INPUT:
169
    tab - Pointer to the network device table.
170
 
171
 */
172
static bool MCF5272_fec_init(struct cyg_netdevtab_entry *tab)
173
{
174
    struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
175
    const u8_t *enaddr;
176
 
177
    /*   Indicate that the ethernet driver is down.                         */
178
 
179
    PMCF5272_FEC_DATA(sc)->operational = ETH_DEV_DOWN;
180
 
181
    /*   Initialize the entire driver private area to zero.                 */
182
 
183
    memset((char*)sc->driver_private, sizeof(MCF5272_fec_priv_data_t), 0);
184
 
185
    /*   Initialize the buffers structure.  This strucre contains  transmit */
186
    /* and receive buffer descriptor managment information.                 */
187
 
188
    nbuf_init(PBUF_INFO(sc));
189
 
190
    /*   Start a alarm that  will trigger  every second.   This alarm  will */
191
    /* periodically update the recevie and transmit statistics.             */
192
 
193
    cyg_clock_to_counter(cyg_real_time_clock(),
194
                         &(((MCF5272_fec_priv_data_t*)sc->driver_private)->counter_h));
195
    cyg_alarm_create(((MCF5272_fec_priv_data_t*)sc->driver_private)->counter_h,
196
                      one_second_alarm_func,
197
                     (cyg_addrword_t)(MCF5272_fec_priv_data_t*)sc->driver_private,
198
                      &(((MCF5272_fec_priv_data_t*)sc->driver_private)->alarm_h),
199
                      &(((MCF5272_fec_priv_data_t*)sc->driver_private)->alarm));
200
    cyg_alarm_initialize(((MCF5272_fec_priv_data_t*)sc->driver_private)->alarm_h,
201
                         cyg_current_time()+
202
                         (1*SEC_IN_NS)/CYGNUM_KERNEL_COUNTERS_RTC_PERIOD,
203
                         (1*SEC_IN_NS)/CYGNUM_KERNEL_COUNTERS_RTC_PERIOD);
204
 
205
    /*   Initialize environment, setup  receive, transmit and  non-critical */
206
    /* interrupt handlers.                                                  */
207
 
208
    cyg_drv_interrupt_create(CYGNUM_HAL_VECTOR_ERX,
209
                             MCF5272_INT_LEVEL, // Priority
210
                             (cyg_addrword_t)sc, //  Data item passed to interrupt handler
211
                             (cyg_ISR_t *)MCF5272_fec_isr,
212
                             (cyg_DSR_t *)eth_drv_dsr,
213
                             &MCF5272_fec_rx_interrupt_handle,
214
                             &MCF5272_fec_rx_interrupt);
215
    cyg_drv_interrupt_create(CYGNUM_HAL_VECTOR_ETX,
216
                             MCF5272_INT_LEVEL, // Priority
217
                             (cyg_addrword_t)sc, //  Data item passed to interrupt handler
218
                             (cyg_ISR_t *)MCF5272_fec_isr,
219
                             (cyg_DSR_t *)eth_drv_dsr,
220
                             &MCF5272_fec_tx_interrupt_handle,
221
                             &MCF5272_fec_tx_interrupt);
222
 
223
    /*   Attach interrupt here in order  to start receiving interrupt  from */
224
    /* the FEC.                                                             */
225
 
226
    cyg_drv_interrupt_attach(MCF5272_fec_rx_interrupt_handle);
227
    cyg_drv_interrupt_attach(MCF5272_fec_tx_interrupt_handle);
228
 
229
 
230
 
231
    put_reg(MCF5272_SIM->gpio.pbcnt, 0x55550000 |
232
            (get_reg(MCF5272_SIM->gpio.pbcnt) & 0x0000FFFF));
233
 
234
 
235
    /*   Reset the FEC - equivalent to a hard reset.                        */
236
 
237
    put_reg(MCF5272_SIM->enet.ecr, MCF5272_FEC_ECR_RESET);
238
 
239
    /*   Wait for the reset sequence to complete.                           */
240
 
241
    while(get_reg(MCF5272_SIM->enet.ecr) & MCF5272_FEC_ECR_RESET);
242
 
243
    /*   Set the Ethernet control register to zero to disable the FEC.      */
244
 
245
    put_reg(MCF5272_SIM->enet.ecr, 0);
246
 
247
    /*   Set the source address for the controller.                         */
248
 
249
    /*   Initialize  physical  address  register  by  copying  our  adapter */
250
    /* address from the device's permanent storage.                         */
251
 
252
    enaddr = (cyg_uint8*)db_get_eth_address();
253
 
254
    put_reg(MCF5272_SIM->enet.malr,0
255
                                       | (enaddr[0] <<24)
256
                                       | (enaddr[1] <<16)
257
                                       | (enaddr[2] <<8)
258
                                       | (enaddr[3] <<0));
259
    put_reg(MCF5272_SIM->enet.maur,0
260
                                       | (enaddr[4] <<24)
261
                                       | (enaddr[5] <<16));
262
 
263
    /*   Initialize the hash  table registers  to ignore  hash checking  to */
264
    /* detect multicast Etherhet addresses.                                 */
265
 
266
    put_reg(MCF5272_SIM->enet.htur, 0);
267
    put_reg(MCF5272_SIM->enet.htlr, 0);
268
 
269
    /*   Set Receive Buffer Size.   This  is  the  size  for  each  receive */
270
    /* buffer.                                                              */
271
 
272
    put_reg(MCF5272_SIM->enet.emrbr, (uint16)RX_BUFFER_SIZE);
273
 
274
    /*   Point to the start of the circular Rx buffer descriptor queue.     */
275
 
276
    put_reg(MCF5272_SIM->enet.erdsr, nbuf_get_start(PBUF_INFO(sc), Rx));
277
 
278
    /*   Point to the start of the circular Tx buffer descriptor queue.     */
279
 
280
    put_reg(MCF5272_SIM->enet.etdsr, nbuf_get_start(PBUF_INFO(sc), Tx));
281
 
282
    /*   Set  the  FIFO  transmit  highwater  mark  to  128  bytes.   Frame */
283
    /* transmission begins when the number of bytes selected by this  field */
284
    /* are written into the  transmit FIFO,  if an  end of  frame has  been */
285
    /* written to the FIFIO, or if the FIFO is full before selected  number */
286
    /* of bytes are written.                                                */
287
 
288
    put_reg(MCF5272_SIM->enet.tfwr, MCF5272_FEC_XWMRK_128);
289
 
290
    /*   Clear any interrupts by setting all bits in the EIR register.      */
291
 
292
    put_reg(MCF5272_SIM->enet.eir, 0xFFFFFFFF);
293
 
294
    /*   Set the tranceiver interface to MII mode.                          */
295
 
296
    put_reg(MCF5272_SIM->enet.rcr, 0 | MCF5272_FEC_RCR_MII_MODE);
297
                                   // | MCF5272_FEC_RCR_DRT);
298
 
299
    /*   Set the mode is ETH_MODE_SIMPLEX.   We are assuming the device  is */
300
    /* half-duplex mode.                                                    */
301
 
302
    PMCF5272_FEC_DATA(sc)->duplex = ETH_MODE_SIMPLEX;
303
 
304
    /* The default speed is 10 Mbs. */
305
 
306
    PMCF5272_FEC_DATA(sc)->speed = ETH_SPEED_10MB;
307
 
308
    /*   Write the maximum  frame  length  and  setup  so  we  can  receive */
309
    /* broadcast packets.                                                   */
310
 
311
    put_reg(MCF5272_SIM->enet.mflr, MCF5272_FEC_MFLR_BRDCAST |
312
            sizeof(eth_frame_hdr));
313
 
314
    /*   Check for heartbeat count  and enable  full-duplex transmit.   The */
315
    /* hearbeat check is performed following end of transmission and the HB */
316
    /* bit in the status  reguster is set if  the collision input does  not */
317
    /* assert within the heartbeat window.                                  */
318
 
319
    /*   NOTE: We disable full  duplex mode  because we  notice that  we're */
320
    /* getting Receive CRC erors.                                           */
321
 
322
 
323
    put_reg(MCF5272_SIM->enet.tcr, 0 |MCF5272_FEC_TCR_HBC);
324
                                   //| MCF5272_FEC_TCR_FDEN);
325
 
326
    /*   Set  the  MII  frequency  divider.   The  MII_SPEED  controls  the */
327
    /* frequency of the MII management  interface  clock  relative  to  the */
328
    /* system clock.  We set MII  speed  to  7  because  the  system  clock */
329
    /* frequency is 66 Mhz.                                                 */
330
 
331
    put_reg(MCF5272_SIM->enet.mscr, 7<<1);
332
 
333
    /*   Initialize upper level driver.                                     */
334
 
335
    (sc->funs->eth_drv->init)(sc, (unsigned char *)enaddr);
336
 
337
    /*   Return  true  to  indicate  that  the  driver  initialization  has */
338
    /* completed successfully.                                              */
339
 
340
    return true;
341
 
342
}
343
 
344
/*      This function is called to  "start up"  the interface.   It may  be */
345
/* called multiple times, even  when the hardware  is already running.   It */
346
/* will be called whenever something "hardware oriented" changes and should */
347
/* leave the hardware ready to send/receive packets.                        */
348
 
349
static void
350
MCF5272_fec_start(struct eth_drv_sc *sc, cyg_uint8 *enaddr, int flags)
351
{
352
 
353
    /*   Initialize the buffers structure.  This strucre contains  transmit */
354
    /* and receive buffer descriptor managment information.  We  initialize */
355
    /* again here becuase we don't  know the internal  state of the  buffer */
356
    /* descriptor pointer in the FEC if the FEC was disabled after  calling */
357
    /* MCF5272_fec_stop.                                                    */
358
 
359
    if (PMCF5272_FEC_DATA(sc)->operational != ETH_DEV_UP)
360
    {
361
        nbuf_init(PBUF_INFO(sc));
362
    }
363
 
364
    /*   Unmask the Transmit and Receive  frame  interrupt  to  handle  the */
365
    /* interrupts.                                                          */
366
 
367
    /*   Unmask the Internal Bus  Errorso we  can detect  any internal  bus */
368
    /* error when the FEC tries to acess the internal bus.                  */
369
 
370
    put_reg(MCF5272_SIM->enet.eimr,
371
            get_reg(MCF5272_SIM->enet.eimr) | MCF5272_FEC_INTERRUPT_MASK);
372
 
373
    /*   Enable FEC.                                                        */
374
 
375
    put_reg(MCF5272_SIM->enet.ecr, MCF5272_FEC_ECR_ETHER_EN);
376
 
377
    /*   Indicate that there have been empty receive buffers produced.      */
378
 
379
    put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
380
 
381
 
382
    /*   Set the flag to indicate that the device is up and running.        */
383
 
384
    PMCF5272_FEC_DATA(sc)->operational = ETH_DEV_UP;
385
 
386
}
387
 
388
/*      A routine to halt the FEC.                                          */
389
static void
390
MCF5272_fec_stop(struct eth_drv_sc *sc)
391
{
392
 
393
    /*   Stop the packet transmission gracefully.                           */
394
 
395
    /*   Set the Graceful Transmit Stop bit.                                */
396
 
397
    put_reg(MCF5272_SIM->enet.tcr, get_reg(MCF5272_SIM->enet.tcr)
398
                                   | MCF5272_FEC_TCR_GTS);
399
 
400
    /*   Wait for the current transmission to complete.                     */
401
 
402
    while( !(get_reg(MCF5272_SIM->enet.eir) & MCF5272_FEC_EIR_GRA));
403
 
404
    /*   Clear the GRA event.                                               */
405
 
406
    put_reg(MCF5272_SIM->enet.eir, MCF5272_FEC_EIR_GRA);
407
 
408
    /*   Disable all FEC interrupts by clearing the IMR register.           */
409
 
410
    put_reg(MCF5272_SIM->enet.eimr,  0);
411
 
412
    /*   Clear the GTS bit so frames can be tranmitted when restarted       */
413
 
414
    put_reg(MCF5272_SIM->enet.tcr, get_reg(MCF5272_SIM->enet.tcr) &
415
                                   ~MCF5272_FEC_TCR_GTS);
416
 
417
    /*   Set the Ethernet control register to zero to disable the FEC.      */
418
 
419
    put_reg(MCF5272_SIM->enet.ecr, 0);
420
 
421
    /*   Deliver any pending frames and acknowledge any transmitted frames.   */
422
 
423
    MCF5272_fec_deliver(sc);
424
 
425
    /*   Set the flag to indicate that the device is down.                  */
426
 
427
    PMCF5272_FEC_DATA(sc)->operational = ETH_DEV_DOWN;
428
 
429
}
430
 
431
/*      This routine is called to perform special "control" opertions.       */
432
 
433
static int
434
MCF5272_fec_control(struct eth_drv_sc *sc, unsigned long key,
435
                    void *data, int data_length)
436
{
437
    switch (key)
438
    {
439
 
440
    case ETH_DRV_SET_MAC_ADDRESS:
441
 
442
        {
443
            /*   Set the hardware address of the Ethernet controller.       */
444
 
445
            struct ifreq* p_ifreq = data;
446
 
447
            /*   If the length of the strcutre is not equal to the size  of */
448
            /* ifreq, then exit with an error.                              */
449
 
450
            if (data_length != sizeof(*p_ifreq))
451
            {
452
                return 0;
453
            }
454
 
455
            /*   Set the lower 4-byte address.                              */
456
 
457
            put_reg(MCF5272_SIM->enet.malr,0
458
                                               | (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[0] <<24)
459
                                               | (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[1] <<16)
460
                                               | (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[2] <<8)
461
                                               | (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[3] <<0));
462
 
463
            /*   Set the upper 2-byte address.                              */
464
 
465
            put_reg(MCF5272_SIM->enet.maur,
466
 
467
                                               | (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[4] <<24)
468
                                               | (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[5] <<16));
469
 
470
 
471
            /*   Return 1 to indicate  that  programming  of  the  new  MAC */
472
            /* address is successful.                                       */
473
 
474
            return 1;
475
        }
476
 
477
 
478
        break;
479
    #ifdef CYGPKG_NET
480
 
481
    case ETH_DRV_GET_IF_STATS:
482
    case ETH_DRV_GET_IF_STATS_UD:
483
 
484
        #if 0
485
        {
486
 
487
            struct ether_drv_stats* pstats = (struct ether_drv_stats*)
488
                                                data;
489
            MCF5272_FEC_DIAG diag;
490
 
491
            /* Retrieve the driver defined diagnostic structure. */
492
            MCF5272_get_stats(sc, &diag);
493
 
494
            strcpy(pstats->description, ether_device_name);
495
            pstats->duplex = ETH_MODE_UNKNWON;
496
            pstats->operational = (unsigned char )PMCF5272_FEC_DATA(sc)->operational;
497
            pstats->speed = 0;
498
 
499
            /*   Translate the device specific  diagnostic  values  to  the */
500
            /* generic ether_drv_stats values.                              */
501
 
502
            /* Get the receive bytes count. */
503
            pstats->rx_count = diag.rx_bytes_cnt;
504
 
505
            /* Get the number of successful packet received. */
506
            pstats->rx_good = diag.rx_pk_cnt;
507
 
508
            /* Get the receive CRC error count. */
509
            pstats->rx_crc_errors = diag.rx_crc_err_cnt;
510
 
511
            /* Get the receive overrun error count. */
512
            pstats->rx_overrun_errors = diag.rx_overrun_err_cnt;
513
 
514
            /* Get the received short frame error count. */
515
            pstats->rx_short_frames = diag.rx_short_frm_err_cnt;
516
 
517
            /* Get the received long frame error count. */
518
            pstats->rx_too_long_frames = diag.rx_long_frm_err_cnt;
519
 
520
            /* Get the number of transmitted bytes. */
521
            pstats->tx_count = diag.tx_bytes_cnt;
522
 
523
            /* Get the number of defered packets. */
524
            pstats->tx_deferred = diag.tx_def_cnt;
525
 
526
            /* The number of successfully transmitted packets. */
527
            pstats->tx_good = diag.tx_pk_cnt;
528
 
529
            /* Get the transmit late collision count. */
530
            pstats->tx_late_collisions = diag.tx_late_col_cnt;
531
 
532
            /* Get the transmit underrun count. */
533
            pstats->tx_underrun = diag.tx_underrun_cnt;
534
 
535
            /* Get the transmit late collision count. */
536
            pstats->tx_total_collisions = diag.tx_late_col_cnt;
537
            return 1;
538
        }
539
        #else
540
        {
541
 
542
            /*   Copy the ethernet name device over.                        */
543
 
544
            strcpy(((struct mcf5272_ether_drv_stats*)data)->description,
545
                   ether_device_name);
546
 
547
            /* Get the stats. */
548
            MCF5272_get_stats(sc,
549
                              &((struct mcf5272_ether_drv_stats*)data)->stats);
550
 
551
            /* Copy the mode over. */
552
 
553
            ((struct mcf5272_ether_drv_stats*)data)->duplex =
554
                PMCF5272_FEC_DATA(sc)->duplex;
555
 
556
            /* The ethernet driver is operational. */
557
 
558
            ((struct mcf5272_ether_drv_stats*)data)->operational =
559
                PMCF5272_FEC_DATA(sc)->operational;
560
 
561
            /*   Copy the speed over.                                       */
562
 
563
            ((struct mcf5272_ether_drv_stats*)data)->speed =
564
                PMCF5272_FEC_DATA(sc)->speed;
565
 
566
            return 1;
567
        }
568
 
569
        #endif
570
        break;
571
 
572
    #endif /* CYGPKG_NET */
573
    default:
574
        return 1;
575
        break;
576
    }
577
 
578
}
579
 
580
 
581
/*      This routine is  called to see  if it is  possible to send  another */
582
/* packet.  It will  return  non-zero  if  a  transmit  is  possible,  zero */
583
/* otherwise.                                                               */
584
 
585
static int
586
MCF5272_fec_can_send(struct eth_drv_sc *sc)
587
{
588
    const int buffer_window = 5; /* Specifies the minimum empty buffer descrpitors */
589
 
590
    if ((NUM_TXBDS - PBUF_INFO(sc)->num_busy_bd) > buffer_window)
591
    {
592
        return 1;
593
    }
594
    else
595
    {
596
        PMCF5272_FEC_DATA(sc)->diag_counters.tx_full_cnt++;
597
        return 0;
598
    }
599
}
600
 
601
 
602
/*      This routine is called  by eCos  to send  a frame  to the  ethernet */
603
/* controller.                                                              */
604
 
605
static void
606
MCF5272_fec_send(struct eth_drv_sc *sc,
607
                 struct eth_drv_sg *sg_list,
608
                 int sg_len,
609
                 int total_len,
610
                 unsigned long key)
611
{
612
 
613
    /*   Call eth_tx_check() routine for any packet transmitted by eCos.    */
614
 
615
    eth_tx_check(sg_list, sg_len);
616
 
617
 
618
    /*   If   we   do   have   enough    buffer    to    send    we    call */
619
    /* MCF5272_fec_common_send routine to send  the packet.  Otherwise,  we */
620
    /* throw away the packet and call eCos's tx_done rutine to notify  that */
621
    /* the packet has been sent.                                            */
622
 
623
    if (NUM_TXBDS - PBUF_INFO(sc)->num_busy_bd > sg_len)
624
    {
625
        MCF5272_fec_common_send(sc, sg_list, sg_len, total_len, key, TX_KEY_ECOS);
626
 
627
 
628
    }
629
    else
630
    {
631
 
632
        CYG_ASSERT(false, "ETH: Send buffer full");
633
 
634
        /*   Inform the upper layer of a completion of the packet.          */
635
 
636
        (sc->funs->eth_drv->tx_done)(sc,
637
                                     key,
638
                                     0);
639
    }
640
 
641
}
642
 
643
/*      This routine is called to send a frame to the ethernet  controller. */
644
/* This is a generic send routine.                                          */
645
/*
646
 
647
  INPUT:
648
    sc - Ethernet driver sc.
649
    sg_glist - scatter gather list.
650
    sg_len - The number of scattter gather entries in the list.
651
    total_len - The total length of the frame.
652
 
653
*/
654
 
655
 
656
static void
657
MCF5272_fec_common_send(struct eth_drv_sc *sc,
658
                        struct eth_drv_sg *sg_list,
659
                        int sg_len,
660
                        int total_len,
661
                        unsigned long key,
662
                        tx_key_type_t key_type)
663
{
664
    int i = 0;
665
    NBUF *pBD = NULL;
666
    NBUF *first_bd;
667
    buf_info_t* p_buf = PBUF_INFO(sc);
668
 
669
 
670
    CYG_ASSERT(sg_len > 0,  "ETH: sg_len cannot be zero");
671
 
672
 
673
    /* Update the number of used transmitted buffer desciptors. */
674
 
675
    p_buf->num_busy_bd += sg_len;
676
 
677
    /*   Keep  track  of  the  maximum  number  of  busy  transmit   buffer */
678
    /* descriptors.                                                         */
679
 
680
    if (p_buf->num_busy_bd > p_buf->max_num_busy_bd)
681
    {
682
        p_buf->max_num_busy_bd = p_buf->num_busy_bd;
683
    }
684
 
685
    /*   Enqueue the key, the index to first and last buffer desriptor, the */
686
    /* number of  buffer descriptors,  the packet  length and  the type  of */
687
    /* packet to the transmit queue.                                        */
688
 
689
    nbuf_enq_tx_key(p_buf, (p_buf->iTxbd + sg_len - 1) % NUM_TXBDS,
690
                    key,
691
                    p_buf->iTxbd,
692
                    sg_len,
693
                    total_len,
694
                    key_type);
695
 
696
    /*   Get the pointer to the first buffer descriptor of the packet.   We */
697
    /* don't set the R bit for the first packet until we have allocated and */
698
    /* initialized all the buffer descriptors.                              */
699
 
700
    first_bd = pBD = nbuf_tx_allocate(p_buf);
701
 
702
    do
703
    {
704
 
705
        CYG_ASSERT(pBD != NULL, "ETH: nbuf_tx_allocate() returned NULL");
706
 
707
 
708
        /*   Copy the address of the buffer and the length to the allocated */
709
        /* buffer descriptor.  Note that  buf_index indexes  to the  buffer */
710
        /* descriptor it returns.                                           */
711
 
712
        pBD->data = (uint8*)sg_list[i].buf;
713
        pBD->length = sg_list[i].len;
714
 
715
        if (i == sg_len - 1)
716
        {
717
 
718
            /*   Set the the L,  TC and R bit  to indicate that the  buffer */
719
            /* descriptor  is  the  last  buffer  descriptor,  the  CRC  is */
720
            /* appended by the FEC and  the buffer descriptor is ready  for */
721
            /* transmission.                                                */
722
 
723
            pBD->status |= TX_BD_L | TX_BD_TC | TX_BD_R;
724
 
725
            /*   When we have  reached the  last buffer  scatther list,  we */
726
            /* break from the loop.                                         */
727
 
728
            break;
729
 
730
        }
731
        else
732
        {
733
 
734
            if (i)
735
            {
736
 
737
                /*   If the buffer  descriptor  is  not  the  first  buffer */
738
                /* descriptor, then set the  R bit to  notify the FEC  that */
739
                /* the buffer descriptor is  read  for  transmission.   FEC */
740
                /* must reset R bit after transmitted for buffer.           */
741
 
742
                pBD->status |= TX_BD_R;
743
 
744
            }
745
 
746
            /*   Allocate the next buffer descriptor.                       */
747
 
748
            pBD = nbuf_tx_allocate(p_buf);
749
 
750
        }
751
 
752
        /*   Advance to the next index.                                     */
753
 
754
        i++;
755
 
756
    }while(1);
757
 
758
    /*   Set the R bit in the first buffer descriptor to indicate that  the */
759
    /* buffer is ready for transmission if  there are more than one  buffer */
760
    /* descriptors.                                                         */
761
 
762
    if (sg_len > 1)
763
        first_bd->status  |= TX_BD_R;
764
 
765
    /*   Indicate that there is a transmit buffer ready.                    */
766
 
767
    put_reg(MCF5272_SIM->enet.tdar, 1);
768
 
769
}
770
 
771
 
772
/*      This function is called  as a result  of the "eth_drv_recv()"  call */
773
/* above.  It's job is to  actually  fetch  data  for  a  packet  from  the */
774
/* hardware once memory buffers have  been allocated for the packet.   Note */
775
/* that the buffers may come in pieces, using a scatter-gather list.   This */
776
/* allows for more efficient processing in the upper layers of the stack.   */
777
 
778
/*      Note that the  total buffer allocated  for the scatter-gather  list */
779
/* can be smaller than the packet or the buffer that in the scatter  gather */
780
/* list is invalid.  This happens when  the upper layer driver runs out  of */
781
/* buffers for the scatter-gather list.                                     */
782
 
783
static void
784
MCF5272_fec_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
785
{
786
    uint_t fill_count = 0, buf_count;
787
    uint_t frame_length = 0, buf_len;
788
    NBUF *pNbuf = NULL;
789
    cyg_uint8* buf = NULL;
790
    cyg_bool_t done = false;
791
    uint_t sg_index = 0;
792
 
793
    /*   If the scatter-gather list is zero,  set buf to NULL so that  this */
794
    /* routine would not copy the buffer to the scatter-gatther buffer.     */
795
 
796
    if (sg_len > 0)
797
    {
798
        buf = (cyg_uint8*)sg_list[0].buf;
799
    }
800
 
801
    do
802
    {
803
 
804
        /*   Get the next buffer descriptor (bd).                           */
805
 
806
        pNbuf = nbuf_rx_get_next(PBUF_INFO(sc));
807
 
808
        CYG_ASSERT(pNbuf != NULL, "Cannot get the next bd");
809
 
810
        if (pNbuf->status & TX_BD_L)
811
        {
812
 
813
            /*   Calculate the remaining numer of bytes in the packet  that */
814
            /* needed to be copied out since  the the length of the in  the */
815
            /* last BD contains the total length of the packet and not  the */
816
            /* length of the buffer.                                        */
817
 
818
            buf_len = (uint_t)pNbuf->length - frame_length;
819
 
820
            /*   Since the last bd, set done  to true in order to exit  the */
821
            /* loop.                                                        */
822
 
823
            done = true;
824
        }
825
        else
826
        {
827
            buf_len = RX_BUFFER_SIZE;
828
 
829
            /*   Update the frame length.                                   */
830
 
831
            frame_length += RX_BUFFER_SIZE;
832
        }
833
 
834
 
835
       /*   Copy the packet to the scatter gather list if there is a buffer */
836
       /* to copy the packet to.                                            */
837
 
838
       for (buf_count = 0; buf_count < buf_len && buf != NULL;)
839
       {
840
 
841
           uint_t copy_len;
842
 
843
           /*   Retrieve the minimum copy length.  We basically copy  based */
844
           /* on the smaller size: the buffer from the scatther list or the */
845
           /* from the buffer descriptor.                                   */
846
 
847
           copy_len =  (((uint_t)sg_list[sg_index].len - fill_count) <
848
                        (buf_len - buf_count) ?
849
                        (uint_t)sg_list[sg_index].len - fill_count :
850
                        (buf_len - buf_count));
851
 
852
           /*   Copy the buffer to the upper layer driver buffer.           */
853
 
854
           memcpy(&buf[fill_count],
855
                  &pNbuf->data[buf_count],
856
                  copy_len);
857
 
858
           /*   Update the counts to reflect the number of bytes copied.    */
859
 
860
           fill_count += copy_len;
861
           buf_count += copy_len;
862
 
863
           /*   If the buffer  in  the  scatter-gather  list  is  full,  we */
864
           /* attempt to retrieve the next buffer in the list.              */
865
 
866
           if (fill_count >= sg_list[sg_index].len)
867
           {
868
 
869
               /*   If there is no more  buffer, set  the buf  to NULL  and */
870
               /* exit the loop.                                            */
871
 
872
               if (++sg_index >= sg_len)
873
               {
874
                   buf = NULL;
875
                   break;
876
               }
877
               else
878
               {
879
                   buf = (cyg_uint8*)sg_list[sg_index].buf;
880
                   fill_count = 0;
881
               }
882
           }
883
       }
884
 
885
 
886
       /*   Release the buffer scriotor so it cab be used to receive  other */
887
       /* packets.                                                          */
888
 
889
        nbuf_rx_release(pNbuf);
890
 
891
    }while(done == false);
892
 
893
    /*   Notify the FEC that there are receive buffer descriptors available */
894
    /* for the FEC.                                                         */
895
 
896
    put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
897
}
898
 
899
/*******************************************************************************
900
MCF5252_fec_recv_handler() - Receive handler to read the received
901
buffer descriptors and inform the upper layer driver of the arrival
902
of the packet.
903
*/
904
inline static
905
bool MCF5252_fec_recv_handler(struct eth_drv_sc * sc)
906
{
907
 
908
    /*   Receive interrupt has occurred informing  driver that a frame  has */
909
    /* been written to the buffer.                                          */
910
 
911
    NBUF* pNBuf;
912
    buf_info_t* p_buf_info = PBUF_INFO(sc);
913
    MCF5272_fec_priv_data_t* eth_data = PMCF5272_FEC_DATA(sc);
914
    uint_t len;
915
 
916
    /*   Pointer to the first buffer descriptor.                            */
917
 
918
    NBUF* p_first_bd;
919
 
920
    /*   Check to see if the buffer descrpitor is not busy.                 */
921
 
922
    if  (nbuf_rx_next_ready(p_buf_info))
923
    {
924
 
925
        /*   Flag that indicates whether the buffer is wrapped.             */
926
 
927
        cyg_bool_t wrap = false;
928
 
929
        /*   Get the index of the buffer desrciptor of the next frame.       */
930
 
931
        uint_t index = nbuf_rx_get_index(p_buf_info);
932
        cyg_bool_t error = false;
933
        len = 0;
934
 
935
        /* Get the pointer to the first buffer descriptor. */
936
 
937
        p_first_bd = nbuf_rx_get(p_buf_info, index);
938
 
939
        do
940
        {
941
            pNBuf = nbuf_rx_get(p_buf_info, index);
942
 
943
            if (pNBuf->status & RX_BD_E)
944
            {
945
 
946
                /*   The buffer is empty or the FEC is stll writing to  the */
947
                /* buffer.  then exit.                                      */
948
 
949
                return false;
950
 
951
            }
952
 
953
            /*   Advance the index  to the  next buffer  descriptor in  the */
954
            /* ring buffer.                                                 */
955
 
956
            index = (index + 1) % NUM_RXBDS;
957
 
958
            if ((pNBuf->status & (RX_BD_L | RX_BD_W)) == RX_BD_W)
959
            {
960
 
961
                /*   If the buffer descriptor wraps, set the wrap flag  and */
962
                /* initalize  the  index  pointer   to  the  first   buffer */
963
                /* descriptor in the ring.                                  */
964
 
965
                wrap = true;
966
 
967
            }
968
 
969
            if (pNBuf->status & RX_BD_TR)
970
            {
971
 
972
                /*   Packet truncate count.                                 */
973
 
974
                eth_data->diag_counters.rx_trunc_error_cnt++;
975
 
976
                /*   Release the bds.                                       */
977
 
978
                nbuf_rx_release_pkt(p_buf_info);
979
 
980
                /*   Update the receive error count.                        */
981
 
982
                eth_data->diag_counters.rx_err_cnt++;
983
 
984
                /*   Notify  the  FEC   that  there   are  receive   buffer */
985
                /* descriptors available from the FEC.                      */
986
 
987
                put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
988
 
989
                error = true;
990
                break;
991
            }
992
 
993
            if (pNBuf->status & RX_BD_L)
994
            {
995
 
996
                /*   Get the length of frame contain in the buffers.        */
997
 
998
                len = pNBuf->length;
999
 
1000
                /*   If there is an  error  in  receiving  the  packet,  we */
1001
                /* proceed to update the counters.  Otherwise, we just fall */
1002
                /* through.                                                 */
1003
 
1004
                if (pNBuf->status & (RX_BD_LG | RX_BD_SH | RX_BD_CR |
1005
                                     RX_BD_OV))
1006
                {
1007
 
1008
                    /*   Update the diagnostic counters.                    */
1009
 
1010
                    if (pNBuf->status & RX_BD_LG)
1011
                    {
1012
                        /* Larget frame error count. */
1013
                        eth_data->diag_counters.rx_long_frm_err_cnt++;
1014
                    }
1015
 
1016
                    if (pNBuf->status & RX_BD_SH)
1017
                    {
1018
                        /* Short  frame error count. */
1019
                        eth_data->diag_counters.rx_short_frm_err_cnt++;
1020
                    }
1021
 
1022
                    if (pNBuf->status & RX_BD_CR)
1023
                    {
1024
                        /* CRC error count. */
1025
                        eth_data->diag_counters.rx_crc_err_cnt++;
1026
                    }
1027
 
1028
                    if (pNBuf->status & RX_BD_OV)
1029
                    {
1030
                        /* Overrun error count. */
1031
                        eth_data->diag_counters.rx_overrun_err_cnt++;
1032
                    }
1033
 
1034
                    /*   Release the packet.                                */
1035
 
1036
                    nbuf_rx_release_pkt(p_buf_info);
1037
 
1038
                    /*   Update the receive error count.                    */
1039
 
1040
                    eth_data->diag_counters.rx_err_cnt++;
1041
 
1042
                    /*   Notify the  FEC  that  there  are  receive  buffer */
1043
                    /* descriptors available for the FEC                    */
1044
 
1045
                    put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
1046
 
1047
                    /*   Set the error flag to true to indicate that  there */
1048
                    /* is an error.                                         */
1049
 
1050
                    error = true;
1051
 
1052
                }
1053
            }
1054
        }while(!(pNBuf->status & RX_BD_L));
1055
 
1056
        if (error == false)
1057
        {
1058
            cyg_uint8* buf_ptr =  p_first_bd->data;
1059
 
1060
            /*   Since there is no error,  we  update  the  good  statistic */
1061
            /* counters.                                                    */
1062
 
1063
            /*   Update the number of frames received.                      */
1064
 
1065
            eth_data->diag_counters.rx_pk_cnt++;
1066
 
1067
            /*   Update the number of bytes in the frame received.          */
1068
 
1069
            /*   Subract  4  bytes  from  the  length  because  the  packet */
1070
            /* includes the 4-byte FCS.                                     */
1071
 
1072
            eth_data->diag_counters.rx_bytes_cnt += (len - 4);
1073
 
1074
 
1075
            /*   If the  packet  wraps  then  copy  the  packet  to  the  a */
1076
            /* temporary buffer in  order  to  make  the  packet  contigous */
1077
            /* packet in memory.                                            */
1078
 
1079
            if (wrap)
1080
            {
1081
 
1082
                uint_t count_len = 0;
1083
                uint_t pk_len;
1084
 
1085
                /*   Set p_buf the pointer to temporary packet biffer which */
1086
                /* we will use to copy the packet.                          */
1087
 
1088
                u8_t* p_buf =  (u8_t*)&eth_data->pkt_buf;
1089
 
1090
                /* Get the index of the buffer desrcitor of the next frame. */
1091
 
1092
                uint_t index = nbuf_rx_get_index(p_buf_info);
1093
 
1094
                do
1095
                {
1096
 
1097
                    /*   Get the buffer descriptor.                         */
1098
 
1099
                    pNBuf = nbuf_rx_get(p_buf_info, index);
1100
 
1101
                    /*   Calculate the  length of  the data  in the  buffer */
1102
                    /* descriptor.  If we reach the last buffer descriptor, */
1103
                    /* the  the  actual  data  size  in  the  last   buffer */
1104
                    /* descriptor is  the number  of bytes  we have  copied */
1105
                    /* less from the value of the length field of the  last */
1106
                    /* buffer descriptor.                                   */
1107
 
1108
                    if (pNBuf->status & RX_BD_L)
1109
                    {
1110
                        pk_len = len - count_len;
1111
                    }
1112
                    else
1113
                    {
1114
                        pk_len = RX_BUFFER_SIZE;
1115
                    }
1116
 
1117
                    /*   Copy the content of  the buffer  to the  temporary */
1118
                    /* packet buffer.                                       */
1119
 
1120
                    memcpy(&p_buf[count_len], pNBuf->data, pk_len);
1121
 
1122
 
1123
                    /*   Keep count of  the number of  bytes read from  the */
1124
                    /* buffer descriptor.                                   */
1125
 
1126
                    count_len += pk_len;
1127
 
1128
                    /*   Advance to the to next buffer descriptor.          */
1129
 
1130
                    index = (index + 1) % NUM_RXBDS;
1131
 
1132
                }while(!(pNBuf->status & RX_BD_L));
1133
 
1134
                buf_ptr = (u8_t*)&eth_data->pkt_buf;
1135
 
1136
 
1137
            }
1138
 
1139
            /*   If there is  a copy  wrap error  or the  Rx packet  filter */
1140
            /* rejected the packet, pass it to the upper layer.  Otherwise, */
1141
            /* release the buffer descriptors.                              */
1142
 
1143
            if (!eth_rx_pkt_filter(buf_ptr, len))
1144
            {
1145
 
1146
                /*   Inform the upper layer of a complete packet.           */
1147
 
1148
                 (sc->funs->eth_drv->recv)(sc, len);
1149
            }
1150
            else
1151
            {
1152
 
1153
                /*   Release the buffer descriptors.                        */
1154
 
1155
                nbuf_rx_release_good_pkt(p_buf_info);
1156
 
1157
 
1158
                /*   Notify the FEC that there is at least a receive buffer */
1159
                /* descriptos available for the FEC.                        */
1160
 
1161
                put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
1162
 
1163
            }
1164
 
1165
        }
1166
 
1167
    }
1168
    else
1169
    {
1170
 
1171
        /*   Indicates that there are no more receive packets.              */
1172
 
1173
        return false;
1174
    }
1175
    return true;
1176
 
1177
}
1178
/*******************************************************************************
1179
MCF5272_fec_transmit_handler() - Transmit handler informs the upper
1180
layer packet of a completion of a transmit packet.
1181
*/
1182
 
1183
static
1184
bool MCF5272_fec_transmit_handler(struct eth_drv_sc * sc)
1185
 
1186
/*      If the FEC has successfull transmitted a packet, then realease  the */
1187
/* buffer used for the packet so that the buffer can be reused.             */
1188
 
1189
{
1190
 
1191
    /*   Check to see which frame has completed sending so we can tell  the */
1192
    /* upper layer to free up ts buffer.                                    */
1193
 
1194
    buf_info_t* p_buf_info = PBUF_INFO(sc);
1195
    MCF5272_fec_priv_data_t* eth_data = PMCF5272_FEC_DATA(sc);
1196
    NBUF* pNbd = NULL;
1197
    int_t index, i;
1198
    tx_keys_t key_entry;
1199
    bool result = true;
1200
    NBUF* next_bd;
1201
 
1202
 
1203
    /*   Check wether there is any pending transmit buffer descriptors that */
1204
    /* are to deallocated.                                                  */
1205
 
1206
    if ((index = nbuf_peek_tx_key(p_buf_info)) != -1)
1207
    {
1208
 
1209
        /*   Get the pointer to the buffer descriptor so that the flags  in */
1210
        /* the status word in the buffer descriptor can be examined.        */
1211
 
1212
        NBUF* pNbuf = nbuf_tx_get(p_buf_info, index);
1213
 
1214
        CYG_ASSERT(pNbuf->status & TX_BD_L, "Index to BD is not the last BD");
1215
 
1216
        if (pNbuf->status & TX_BD_R)
1217
        {
1218
 
1219
 
1220
            /*   Increment the number of times the device driver  discovers */
1221
            /* that the buffer descriptor is still in use by the FEC and it */
1222
            /* has been skipped.                                            */
1223
 
1224
            if ((next_bd = nbuf_peek_bd_ahead(p_buf_info)))
1225
            {
1226
                if (!(next_bd->status & TX_BD_R) &&
1227
                    pNbuf->status & TX_BD_R)
1228
                {
1229
 
1230
                    eth_data->diag_counters.tx_not_complete_cnt++;
1231
                    goto RELEASE_BUF;
1232
 
1233
                }
1234
            }
1235
 
1236
            /*   If the buffer not ready we return immediatly.               */
1237
 
1238
            return false;
1239
 
1240
         }
1241
 
1242
RELEASE_BUF:
1243
 
1244
        /*   Dequeue the packet from the trasnmt packet queue to  indicate */
1245
        /* that the packet is not being transmitted by the FEC.            */
1246
 
1247
        nbuf_deq_tx_key(p_buf_info, &key_entry);
1248
 
1249
        /*   Release the used buffers.                                     */
1250
 
1251
        for ( i = 0; i < key_entry.num_dbufs; i++)
1252
 
1253
        {
1254
 
1255
            /*   Get the BD based on the index.                            */
1256
 
1257
            pNbd = nbuf_tx_get(p_buf_info,
1258
                              (key_entry.start_index + i) % NUM_TXBDS);
1259
 
1260
            /*   The last buffer descriptor of the packet.                 */
1261
 
1262
            if (pNbd->status & TX_BD_L)
1263
            {
1264
 
1265
                if (pNbd->status & TX_BD_RL)
1266
                {
1267
 
1268
                    /*   Update the number of retries.                     */
1269
 
1270
                    eth_data->diag_counters.tx_retry_cnt += 16;
1271
                    eth_data->diag_counters.tx_err_cnt++;
1272
                    eth_data->diag_counters.tx_exes_retry_cnt++;
1273
                }
1274
                else
1275
                {
1276
 
1277
                    /*   Check for  error status.   If there  is an  error */
1278
                    /* proceed the  increment  the  appropriate  statistic */
1279
                    /* counter.                                            */
1280
 
1281
                    if (pNbd->status  & (TX_BD_UN |
1282
                                         TX_BD_LC |
1283
                                         TX_BD_CSL |
1284
                                         TX_BD_HB))
1285
                    {
1286
 
1287
                        if (pNbd->status & TX_BD_HB)
1288
                        {
1289
 
1290
                            /*   Heartbeat error count.                     */
1291
 
1292
                            eth_data->diag_counters.tx_hb_err_cnt++;
1293
                        }
1294
 
1295
                        if (pNbd->status & TX_BD_UN)
1296
                        {
1297
 
1298
                            /*   Transmit underrun error count.             */
1299
 
1300
                            eth_data->diag_counters.tx_underrun_cnt++;
1301
                        }
1302
 
1303
                        if (pNbd->status & TX_BD_CSL)
1304
                        {
1305
 
1306
                            /*   Transmit carrier loss count.               */
1307
 
1308
                            eth_data->diag_counters.tx_carrrier_loss_cnt++;
1309
                        }
1310
 
1311
                        if (pNbd->status & TX_BD_LC)
1312
                        {
1313
 
1314
                            /*   Update the late collision counter.         */
1315
 
1316
                            eth_data->diag_counters.tx_late_col_cnt++;
1317
                        }
1318
 
1319
                        /*   Update the number transmit error count.       */
1320
 
1321
                        eth_data->diag_counters.tx_err_cnt++;
1322
                    }
1323
                    else
1324
                    {
1325
                        /* Update the diagnostic counters */
1326
 
1327
                        if (pNbd->status & TX_BD_DEF)
1328
                        {
1329
                            /* Defer indication count. */
1330
                            eth_data->diag_counters.tx_def_cnt++;
1331
                        }
1332
 
1333
                        /*   Update the number of transmitted packets.     */
1334
 
1335
                        eth_data->diag_counters.tx_pk_cnt++;
1336
 
1337
                        /*   Update the  transmitted packet  size.  If  the */
1338
                        /* size is less than the minimum size then take the */
1339
                        /* minimum size as the  actual frame length.   This */
1340
                        /* is because we take account of the pad bytes that */
1341
                        /* the FEC appends when  it sends  out frames  that */
1342
                        /* has less than the minimum length.                */
1343
 
1344
                        eth_data->diag_counters.tx_bytes_cnt +=
1345
                            key_entry.pk_len < ETH_MIN_SIZE ? ETH_MIN_SIZE :
1346
                            key_entry.pk_len;
1347
                    }
1348
 
1349
                    /*   Get the number of retries.                        */
1350
 
1351
                    eth_data->diag_counters.tx_retry_cnt +=
1352
                        (pNbd->status >> 2) & 0xF;
1353
                }
1354
 
1355
            }
1356
 
1357
            /*   Release the buffer descriptor so that it can be reused to */
1358
            /* transmit the next packet.                                   */
1359
 
1360
            nbuf_tx_release(pNbd);
1361
 
1362
            /*   If the start_index is the same  as the index to the  last */
1363
            /* buffer descriptor, then quit the loop.                      */
1364
 
1365
        }
1366
 
1367
        /*   Decrement the number of busy descriptors.                     */
1368
 
1369
        p_buf_info->num_busy_bd -=  key_entry.num_dbufs;
1370
 
1371
         switch(key_entry.key_type)
1372
         {
1373
             case TX_KEY_ECOS:
1374
 
1375
             /*   Inform the upper layer of a completion of the packet.     */
1376
 
1377
             (sc->funs->eth_drv->tx_done)(sc,
1378
                                         key_entry.tx_key,
1379
                                         0);
1380
             break;
1381
         case TX_KEY_USER:
1382
 
1383
             /*   Inform the application of the completion of the packet.   */
1384
 
1385
             eth_send_done(key_entry.tx_key);
1386
             break;
1387
         }
1388
 
1389
    }
1390
    else
1391
    {
1392
 
1393
        /*   Retrun false to indicate that the transmit buffer is empty.    */
1394
 
1395
        result =  false;
1396
    }
1397
 
1398
    /*   Indicate  that  the  packet  at  the  transmit  buffer  has   been */
1399
    /* successfully handled.                                                */
1400
 
1401
    return result;
1402
}
1403
 
1404
 
1405
/*      This routine informs  the upper  layer of  a completion  of a  sent */
1406
/* frame and a reception of a frame.                                        */
1407
 
1408
static void
1409
MCF5272_fec_deliver(struct eth_drv_sc * sc)
1410
{
1411
    u32_t event;
1412
 
1413
 
1414
    /*   Clear the event register.                                          */
1415
 
1416
    put_reg(MCF5272_SIM->enet.eir,
1417
            (event = (get_reg(MCF5272_SIM->enet.eir) &
1418
                      MCF5272_FEC_INTERRUPT_MASK)));
1419
 
1420
    while(event & MCF5272_FEC_INTERRUPT_MASK)
1421
    {
1422
 
1423
        /*   This flag will  specifies  whether  we  need  to  service  the */
1424
        /* transmit or receive sides of the Ethernet controller.            */
1425
 
1426
        bool packet_status;
1427
 
1428
 
1429
        /*   Keep count of  any bus  error that  might occur  when the  FEC */
1430
        /* attempts while the FEC accessing the internal bus.               */
1431
 
1432
        if (event & MCF5272_FEC_EIR_EBERR)
1433
        {
1434
            PMCF5272_FEC_DATA(sc)->diag_counters.internal_bus_error_cnt++;
1435
        }
1436
 
1437
        do
1438
        {
1439
            packet_status = false;
1440
 
1441
            /*   Call receive the handler to receive packets.               */
1442
 
1443
            packet_status |= MCF5252_fec_recv_handler(sc);
1444
 
1445
            /*   Call transit the handed to release the transmit buffers.   */
1446
 
1447
            packet_status |= MCF5272_fec_transmit_handler(sc);
1448
 
1449
            /*   Loop back up  until all the  receive and transmit  buffers */
1450
            /* are empty.                                                   */
1451
 
1452
        }while(packet_status);
1453
 
1454
        /*   Retrieve the next interrupt event.                             */
1455
 
1456
        /*   Clear the event register.                                      */
1457
 
1458
        put_reg(MCF5272_SIM->enet.eir,
1459
                event = (get_reg(MCF5272_SIM->enet.eir) &
1460
                         MCF5272_FEC_INTERRUPT_MASK));
1461
 
1462
    }
1463
 
1464
    /*   NOTE: If the a bit in the eir is set after clearing the bit in the */
1465
    /* eir, unmasking the bit in the imr will generate an interrupt.   This */
1466
    /* assumption is true only if the interrupt line to the  microprocessor */
1467
    /* core is level sensitive.                                             */
1468
 
1469
    /*   Allow interrupts by setting IMR register.                          */
1470
 
1471
        put_reg(MCF5272_SIM->enet.eimr, get_reg(MCF5272_SIM->enet.eimr) |
1472
                                    MCF5272_FEC_INTERRUPT_MASK
1473
                                    );
1474
 
1475
}
1476
 
1477
/*      Generic Interrupt Service Routine.  This  routine wakes up the  DSR */
1478
/* for further processing.                                                  */
1479
 
1480
static int
1481
MCF5272_fec_isr(cyg_vector_t vector, cyg_addrword_t data,
1482
                HAL_SavedRegisters *regs)
1483
{
1484
 
1485
    /*   Mask  the  FEC's  interrupts  so  that  it  won't  generate  these */
1486
    /* interrupts anymore as the driver  reads the packets or  acknowledges */
1487
    /* packets.                                                             */
1488
 
1489
    put_reg(MCF5272_SIM->enet.eimr, get_reg(MCF5272_SIM->enet.eimr) &
1490
            ~(MCF5272_FEC_INTERRUPT_MASK));
1491
 
1492
    return CYG_ISR_CALL_DSR;
1493
}
1494
 
1495
 
1496
/*      Call MCF5272_fec_deliver() to poll the FEC.                         */
1497
 
1498
static void
1499
MCF5272_fec_int(struct eth_drv_sc *sc)
1500
{
1501
    MCF5272_fec_deliver(sc);
1502
}
1503
 
1504
static int
1505
MCF5272_fec_int_vector(struct eth_drv_sc *sc)
1506
{
1507
 
1508
    /*   How do you return multiple interrupt vector?                       */
1509
 
1510
    return CYGNUM_HAL_VECTOR_ERX;
1511
}
1512
 
1513
/*      This routine updates the Ethernet statistics counters.  This method */
1514
/* is called by eCos every second.                                          */
1515
 
1516
static void one_second_alarm_func(cyg_handle_t alarm, cyg_addrword_t data)
1517
{
1518
    #define WRAP_SUBTRACT(_VAL1_,_VAL2_) \
1519
        ({unsigned long val;if (_VAL1_ >= _VAL2_) val = _VAL1_ - _VAL2_; \
1520
         else val=(0-_VAL2_)+_VAL1_; val;})
1521
 
1522
    ((MCF5272_fec_priv_data_t*)data)->diag_counters.rx_bytes_cnt_sec =
1523
        WRAP_SUBTRACT(
1524
            ((MCF5272_fec_priv_data_t*)data)->diag_counters.rx_bytes_cnt,
1525
            ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_rx_bytes_cnt);
1526
 
1527
    ((MCF5272_fec_priv_data_t*)data)->diag_counters.tx_bytes_cnt_sec =
1528
        WRAP_SUBTRACT(
1529
            ((MCF5272_fec_priv_data_t*)data)->diag_counters.tx_bytes_cnt,
1530
            ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_tx_bytes_cnt);
1531
 
1532
    ((MCF5272_fec_priv_data_t*)data)->diag_counters.rx_pk_cnt_sec =
1533
        WRAP_SUBTRACT(
1534
            ((MCF5272_fec_priv_data_t*)data)->diag_counters.rx_pk_cnt,
1535
            ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_rx_pk_cnt);
1536
 
1537
    ((MCF5272_fec_priv_data_t*)data)->diag_counters.tx_pk_cnt_sec =
1538
        WRAP_SUBTRACT(
1539
            ((MCF5272_fec_priv_data_t*)data)->diag_counters.tx_pk_cnt,
1540
            ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_tx_pk_cnt);
1541
 
1542
 
1543
    ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_rx_bytes_cnt =
1544
        ((MCF5272_fec_priv_data_t*)data)->diag_counters.rx_bytes_cnt;
1545
    ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_tx_bytes_cnt =
1546
        ((MCF5272_fec_priv_data_t*)data)->diag_counters.tx_bytes_cnt;
1547
    ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_rx_pk_cnt =
1548
        ((MCF5272_fec_priv_data_t*)data)->diag_counters.rx_pk_cnt;
1549
    ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_tx_pk_cnt =
1550
        ((MCF5272_fec_priv_data_t*)data)->diag_counters.tx_pk_cnt;
1551
}
1552
 
1553
/*      Retrieve the stats information.                                     */
1554
 
1555
void MCF5272_get_stats(struct eth_drv_sc *sc, MCF5272_FEC_DIAG* stats)
1556
{
1557
    memcpy(stats, &PMCF5272_FEC_DATA(sc)->diag_counters,
1558
           sizeof (MCF5272_FEC_DIAG));
1559
 
1560
    /*   Retrieve the  number  of  available  buffer  descriptors  and  the */
1561
    /* minimum value.                                                       */
1562
 
1563
    PMCF5272_FEC_DATA(sc)->diag_counters.tx_free_bd_cnt =
1564
        NUM_TXBDS - PBUF_INFO(sc)->num_busy_bd;
1565
    PMCF5272_FEC_DATA(sc)->diag_counters.tx_free_min_bd_cnt =
1566
        NUM_TXBDS - PBUF_INFO(sc)->max_num_busy_bd;
1567
}
1568
 
1569
 
1570
/*****************************************************************************
1571
 
1572
     The following  functions  provide  an  interface  directly  to  the
1573
ethernet driver for applications that wish to circumvent the IP stack.
1574
 
1575
     Applications that wish  to take advantage  of this should  override
1576
these routine with their own.  Leaving these routines as default  routes
1577
all data through the IP stack.
1578
 
1579
*****************************************************************************/
1580
 
1581
/*****************************************************************************
1582
eth_rx_pkt_filter -- Ethernet receive packet filter
1583
 
1584
     This is an ethernet packet filter function that allows the application
1585
to receive raw ethernet frames from  the driver.  The return value of  this
1586
function determines whether or not to pass the packet to the IP stack.
1587
 
1588
     We declare it weak so that other routine can override it.
1589
 
1590
INPUT:
1591
 
1592
     pkt: Pointer to the packet.
1593
 
1594
     pkt_len: The length of  the packet including  all headers, the  32-bit
1595
Ethernet CRC, and any Ethernet frame padding.
1596
 
1597
OUTPUT:
1598
 
1599
RETURN VALUE:
1600
 
1601
     true: Do not send the packet to the IP stack.
1602
 
1603
     false: Send the packet to the IP stack.
1604
 
1605
*****************************************************************************/
1606
int_t eth_rx_pkt_filter(u8_t * pkt, uint_t pkt_len)
1607
{
1608
 
1609
    /*   Always return false by default. */
1610
 
1611
    return false;
1612
}
1613
 
1614
/*****************************************************************************
1615
eth_tx_check -- Watch transmitting Ethernet packets
1616
 
1617
     The driver calls this routine before transmitting packets from  the
1618
IP stack.  It provides a hook for applications to watch all packets that
1619
the IP stack transmits.
1620
 
1621
     We declare it weak so that other routine can override it.
1622
 
1623
INPUT:
1624
 
1625
     sg_list: Pointer to the scatter-gather list.
1626
 
1627
     sg_len: The number of scatter-gather entries in the list.
1628
 
1629
OUTPUT:
1630
 
1631
RETURN VALUE:
1632
 
1633
     None
1634
 
1635
*****************************************************************************/
1636
void eth_tx_check(struct eth_drv_sg * sg_list, unsigned int sg_len)
1637
{
1638
 
1639
    /*   Do nothing by default.                                             */
1640
 
1641
}
1642
 
1643
/*****************************************************************************
1644
eth_send -- Transmit a raw Ethernet packet
1645
 
1646
     This function sends  a  packet  to  the  Ethernet  controller  thus
1647
passing the eCos IP stack.
1648
 
1649
     Note that the application must reuse the buffer parameters to  this
1650
function until the driver releases  the buffer with the  eth_send_done()
1651
function.
1652
 
1653
INPUT:
1654
 
1655
     sg_list: Pointer to the scatter-gather list to send.
1656
 
1657
     sg_len: The size of the scatter-gather list.
1658
 
1659
     tag: A value  that  we  pass  as  a  parameter  to  eth_send_done()
1660
function when the FEC has completed sending the packet.
1661
 
1662
OUTPUT:
1663
 
1664
RETURN VALUE:
1665
 
1666
     true: if the packet is  successfully queued to the device  driver's
1667
queue.
1668
 
1669
     false : If the routine fails to send the packet.
1670
 
1671
*****************************************************************************/
1672
int_t eth_send(struct eth_drv_sg* sg_list, unsigned int sg_len,
1673
              int total_len,
1674
              unsigned long tag)
1675
{
1676
    int_t success;
1677
    cyg_uint32 s;
1678
 
1679
    s = cyg_splsoftnet();
1680
 
1681
    /*   If there is enough  buffer  descriptors,  then  send  the  packet. */
1682
    /* Otherwise, throw the packet away and return a false value.           */
1683
 
1684
    if (NUM_TXBDS - PBUF_INFO(&MCF5272_fec_sc)->num_busy_bd > sg_len)
1685
    {
1686
 
1687
        /*   Call the common send routine to send the packet.               */
1688
 
1689
        MCF5272_fec_common_send(&MCF5272_fec_sc,
1690
                                sg_list,
1691
                                sg_len,
1692
                                total_len,
1693
                                tag,
1694
                                TX_KEY_USER);
1695
 
1696
        success = true;
1697
    }
1698
    else
1699
    {
1700
 
1701
        /*   Fail to send the packet.                                       */
1702
 
1703
        success = false;
1704
    }
1705
 
1706
    /*   Release the Ethernet driver lock.                                  */
1707
 
1708
    cyg_splx(s);
1709
 
1710
    return success;
1711
}
1712
 
1713
/*****************************************************************************
1714
eth_send_done -- eth_send callback
1715
 
1716
     The driver calls this  function when  it has  sent out  the packet.   The
1717
parameter tag is the same  value as the  tag value when  the caller calls  the
1718
eth_send to send the packet.
1719
 
1720
     We declare it weak so that other routine can override it.
1721
 
1722
INPUT:
1723
 
1724
     tag: A value  that  we  pass  as  a  parameter  to  eth_send_done()
1725
function when the FEC has completed sending the packet.
1726
 
1727
OUTPUT:
1728
 
1729
RETURN VALUE:
1730
 
1731
     None
1732
 
1733
*****************************************************************************/
1734
void eth_send_done(unsigned long tag)
1735
{
1736
 
1737
}
1738
 
1739
 
1740
#if 0
1741
 
1742
 
1743
/* Defined Ethernet Frame Types */
1744
#define FRAME_IP        (0x0800)
1745
#define FRAME_ARP       (0x0806)
1746
#define FRAME_RARP      (0x8035)
1747
 
1748
/* Offset and size of protocol headers */
1749
#define ETH_HDR_OFFSET  0        /* Ethernet header at the top of the frame */
1750
#define ETH_HDR_SIZE    14
1751
 
1752
/* Assign a protocol number for the loop test */
1753
static uint16 eth_type = 0x0300;
1754
 
1755
/* Global variable containing length of data to transmit */
1756
static uint16 data_length = 512;
1757
 
1758
/* Transmit data size of each transmti buffer descriptor. */
1759
 
1760
#define TX_BUFFER_SIZE (576)    /* must be divisible by 16 */
1761
 
1762
 
1763
void
1764
fec_start_loopback_test(void)
1765
{
1766
    /* Initalize the buffer descriptors. */
1767
 
1768
    nbuf_init(&MCF5272_fec_priv_data.nbuffer);
1769
 
1770
    /* Initalize the Ethernet controllder device. */
1771
 
1772
    MCF5272_fec_init(&MCF5272_fec_netdev);
1773
 
1774
 
1775
}
1776
 
1777
/********************************************************************/
1778
static void
1779
loop_fill_buffers(void)
1780
{
1781
        /* Fill all the buffers in the TX buffer ring with a unique data pattern */
1782
        uint16 index, pattern, i;
1783
    static unsigned char output_buffer[NUM_TXBDS][TX_BUFFER_SIZE];
1784
 
1785
 
1786
    uint_t data_length = TX_BUFFER_SIZE;
1787
 
1788
        for (i = 0; i < NUM_TXBDS; i++)
1789
        {
1790
 
1791
        MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data = output_buffer[i];
1792
                switch (i % 8)
1793
                {
1794
                        /* Load buffers 0 through 3 with a single data patterns */
1795
                        case (0):
1796
                                memset(&MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[ETH_HDR_SIZE],0x55,data_length);
1797
                                break;
1798
                        case (1):
1799
                                memset(&MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[ETH_HDR_SIZE],0xAA,data_length);
1800
                                break;
1801
                        case (2):
1802
                                memset(&MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[ETH_HDR_SIZE],0x00,data_length);
1803
                                break;
1804
                        case (3):
1805
                                memset(&MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[ETH_HDR_SIZE],0xFF,data_length);
1806
                                break;
1807
 
1808
                        /* Buffer[4]: Load increasing walking ones */
1809
                        case (4):
1810
                                pattern = 1;
1811
                                for (index = 0; index < data_length; index++)
1812
                                {
1813
                                        if (pattern == 0x0100)
1814
                                                pattern = 0x01;
1815
                                        MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[index] = (uint8)pattern;
1816
                                        pattern <<= 1;
1817
                                }
1818
                                break;
1819
 
1820
                        /* Buffer[5]: Load decreasing walking ones */
1821
                        case(5):
1822
                                pattern = 0x80;
1823
                                for (index = 0; index < data_length; index++)
1824
                                {
1825
                                        if (pattern == 0x00)
1826
                                                pattern = 0x80;
1827
                                        MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[index] = (uint8)pattern;
1828
                                        pattern >>= 1;
1829
                                }
1830
                                break;
1831
 
1832
                        /* Buffer[6]: Load "Increment from 0" pattern */
1833
                        case (6):
1834
                                for (index = 0; index < data_length; index++)
1835
                                        MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[index] = (uint8) ((index-14)%256);
1836
                                break;
1837
 
1838
                        /* Buffer[7]: Load "Decrement from 255" pattern */
1839
                        case (7):
1840
                                for (index = 0; index < data_length; index++)
1841
                                        MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[index] = (uint8)(255- ((index-14)%256));
1842
                                break;
1843
                }
1844
        }
1845
}
1846
 
1847
/********************************************************************/
1848
void
1849
loop_handler(void)
1850
{
1851
 
1852
    /*   This is the loop  specific RX  handler called  from the  interrupt */
1853
    /* receive routine.  This routine  gets  bound  to  the  loop  protocol */
1854
    /* (0x0300) by  a call  to nif_bind_protocol()  and is  then called  in */
1855
    /* fec_receive().  This function  simply checks to  make sure that  the */
1856
    /* receive buffer matches the transmit buffer.                          */
1857
 
1858
        int i;
1859
 
1860
        /* Compare what I received to what I transmitted */
1861
        for (i = 0; i < (data_length + ETH_HDR_SIZE); i++)
1862
        {
1863
                if (TxBuffer[fec_nif->f_rx % NUM_TXBDS].data[i] != pNbuf->data[i])
1864
                {
1865
                        /* Increment reception error count */
1866
                        fec_nif->f_rx_err++;
1867
                }
1868
        }
1869
 
1870
        /* Increment reception count */
1871
        fec_nif->f_rx++;
1872
 
1873
        /* Update progress indicator */
1874
        if (!(fec_nif->f_rx % 200))
1875
        {
1876
                ihash = (ihash + 1) % 4;
1877
                diag_printf("\b%c",hash[ihash]);
1878
        }
1879
 
1880
        return;
1881
}
1882
 
1883
#endif
1884
 
1885
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.