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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [devs/] [eth/] [mcf52xx/] [mcf5272/] [v2_0/] [src/] [if_mcf5272.c] - Blame information for rev 276

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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