]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/eth/mcf52xx/mcf5272/v2_0/src/if_mcf5272.c
Initial revision
[karo-tx-redboot.git] / packages / devs / eth / mcf52xx / mcf5272 / v2_0 / src / if_mcf5272.c
1 //==========================================================================
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                                            0
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