1 //==========================================================================
3 // dev/if_MCF5272_fec.c
5 // Ethernet device driver for MCF5272's Fast Ethernet Controller (FEC)
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.
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.
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
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.
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.
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.
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 //==========================================================================
43 // Ethernet device driver for Fast Ethernet MCF5272_fec
44 #include <pkgconf/io_eth_drivers.h>
46 #include <cyg/hal/drv_api.h>
47 #include <cyg/io/eth/netdev.h>
48 #include <cyg/io/eth/eth_drv.h>
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>
54 #include <cyg/infra/cyg_ass.h>
55 #include <sys/param.h>
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.
64 db_get_eth_address(void) __attribute__ ((weak));
67 /*****************************************************************************
69 The following functions provide an interface directly to the
70 ethernet driver for applications that wish to circumvent the IP stack.
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.
76 *****************************************************************************/
78 eth_rx_pkt_filter(u8_t* pkt, uint_t pkt_len) __attribute__ ((weak));
80 eth_tx_check(struct eth_drv_sg * sg_list, unsigned int sg_len)
81 __attribute__ ((weak));
83 eth_send_done(unsigned long tag) __attribute__ ((weak));
85 eth_send(struct eth_drv_sg * sg_list, unsigned int sg_len, int total_len,
88 static MCF5272_fec_priv_data_t MCF5272_fec_priv_data;
90 /* Interrupt strcture and handles. */
91 static cyg_interrupt MCF5272_fec_rx_interrupt;
92 static cyg_interrupt MCF5272_fec_tx_interrupt;
94 static cyg_handle_t MCF5272_fec_rx_interrupt_handle;
95 static cyg_handle_t MCF5272_fec_tx_interrupt_handle;
99 static void MCF5272_fec_int(struct eth_drv_sc *sc);
100 static int MCF5272_fec_int_vector(struct eth_drv_sc *sc);
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);
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);
111 MCF5272_fec_common_send(struct eth_drv_sc *sc,
112 struct eth_drv_sg *sg_list, int sg_len,
115 tx_key_type_t key_type);
118 MCF5272_fec_isr(cyg_vector_t vector, cyg_addrword_t data,
119 HAL_SavedRegisters *regs);
122 // One-second call back alarm
123 static void one_second_alarm_func(cyg_handle_t alarm, cyg_addrword_t data);
125 // Retrieve statistics
126 static void MCF5272_get_stats(struct eth_drv_sc *sc, MCF5272_FEC_DIAG* stats);
129 ETH_DRV_SC(MCF5272_fec_sc,
130 &MCF5272_fec_priv_data, // Driver specific data
131 "eth0", // Name for this interface
135 MCF5272_fec_can_send,
140 MCF5272_fec_int_vector);
143 static const char ether_device_name[] = "MCF5272-eth";
145 NETDEVTAB_ENTRY(MCF5272_fec_netdev,
151 /*******************************************************************************
152 db_get_eth_address() - Returns the default Ethernet address.
154 const void* db_get_eth_address(void)
157 /* Just use an obviously invalid address until someone overrides this */
158 /* routine to provide their own address. */
160 static const unsigned char enaddr[] =
162 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
164 return (const void*)enaddr;
166 /*******************************************************************************
167 MCF5272_fec_init() - Routine that initializes the FEC.
170 tab - Pointer to the network device table.
173 static bool MCF5272_fec_init(struct cyg_netdevtab_entry *tab)
175 struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
178 /* Indicate that the ethernet driver is down. */
180 PMCF5272_FEC_DATA(sc)->operational = ETH_DEV_DOWN;
182 /* Initialize the entire driver private area to zero. */
184 memset((char*)sc->driver_private, sizeof(MCF5272_fec_priv_data_t), 0);
186 /* Initialize the buffers structure. This strucre contains transmit */
187 /* and receive buffer descriptor managment information. */
189 nbuf_init(PBUF_INFO(sc));
191 /* Start a alarm that will trigger every second. This alarm will */
192 /* periodically update the recevie and transmit statistics. */
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,
203 (1*SEC_IN_NS)/CYGNUM_KERNEL_COUNTERS_RTC_PERIOD,
204 (1*SEC_IN_NS)/CYGNUM_KERNEL_COUNTERS_RTC_PERIOD);
206 /* Initialize environment, setup receive, transmit and non-critical */
207 /* interrupt handlers. */
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);
224 /* Attach interrupt here in order to start receiving interrupt from */
227 cyg_drv_interrupt_attach(MCF5272_fec_rx_interrupt_handle);
228 cyg_drv_interrupt_attach(MCF5272_fec_tx_interrupt_handle);
232 put_reg(MCF5272_SIM->gpio.pbcnt, 0x55550000 |
233 (get_reg(MCF5272_SIM->gpio.pbcnt) & 0x0000FFFF));
236 /* Reset the FEC - equivalent to a hard reset. */
238 put_reg(MCF5272_SIM->enet.ecr, MCF5272_FEC_ECR_RESET);
240 /* Wait for the reset sequence to complete. */
242 while(get_reg(MCF5272_SIM->enet.ecr) & MCF5272_FEC_ECR_RESET);
244 /* Set the Ethernet control register to zero to disable the FEC. */
246 put_reg(MCF5272_SIM->enet.ecr, 0);
248 /* Set the source address for the controller. */
250 /* Initialize physical address register by copying our adapter */
251 /* address from the device's permanent storage. */
253 enaddr = (cyg_uint8*)db_get_eth_address();
255 put_reg(MCF5272_SIM->enet.malr,0
260 put_reg(MCF5272_SIM->enet.maur,0
264 /* Initialize the hash table registers to ignore hash checking to */
265 /* detect multicast Etherhet addresses. */
267 put_reg(MCF5272_SIM->enet.htur, 0);
268 put_reg(MCF5272_SIM->enet.htlr, 0);
270 /* Set Receive Buffer Size. This is the size for each receive */
273 put_reg(MCF5272_SIM->enet.emrbr, (uint16)RX_BUFFER_SIZE);
275 /* Point to the start of the circular Rx buffer descriptor queue. */
277 put_reg(MCF5272_SIM->enet.erdsr, nbuf_get_start(PBUF_INFO(sc), Rx));
279 /* Point to the start of the circular Tx buffer descriptor queue. */
281 put_reg(MCF5272_SIM->enet.etdsr, nbuf_get_start(PBUF_INFO(sc), Tx));
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. */
289 put_reg(MCF5272_SIM->enet.tfwr, MCF5272_FEC_XWMRK_128);
291 /* Clear any interrupts by setting all bits in the EIR register. */
293 put_reg(MCF5272_SIM->enet.eir, 0xFFFFFFFF);
295 /* Set the tranceiver interface to MII mode. */
297 put_reg(MCF5272_SIM->enet.rcr, 0 | MCF5272_FEC_RCR_MII_MODE);
298 // | MCF5272_FEC_RCR_DRT);
300 /* Set the mode is ETH_MODE_SIMPLEX. We are assuming the device is */
301 /* half-duplex mode. */
303 PMCF5272_FEC_DATA(sc)->duplex = ETH_MODE_SIMPLEX;
305 /* The default speed is 10 Mbs. */
307 PMCF5272_FEC_DATA(sc)->speed = ETH_SPEED_10MB;
309 /* Write the maximum frame length and setup so we can receive */
310 /* broadcast packets. */
312 put_reg(MCF5272_SIM->enet.mflr, MCF5272_FEC_MFLR_BRDCAST |
313 sizeof(eth_frame_hdr));
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. */
320 /* NOTE: We disable full duplex mode because we notice that we're */
321 /* getting Receive CRC erors. */
324 put_reg(MCF5272_SIM->enet.tcr, 0 |MCF5272_FEC_TCR_HBC);
325 //| MCF5272_FEC_TCR_FDEN);
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. */
332 put_reg(MCF5272_SIM->enet.mscr, 7<<1);
334 /* Initialize upper level driver. */
336 (sc->funs->eth_drv->init)(sc, (unsigned char *)enaddr);
338 /* Return true to indicate that the driver initialization has */
339 /* completed successfully. */
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. */
351 MCF5272_fec_start(struct eth_drv_sc *sc, cyg_uint8 *enaddr, int flags)
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. */
360 if (PMCF5272_FEC_DATA(sc)->operational != ETH_DEV_UP)
362 nbuf_init(PBUF_INFO(sc));
365 /* Unmask the Transmit and Receive frame interrupt to handle the */
368 /* Unmask the Internal Bus Errorso we can detect any internal bus */
369 /* error when the FEC tries to acess the internal bus. */
371 put_reg(MCF5272_SIM->enet.eimr,
372 get_reg(MCF5272_SIM->enet.eimr) | MCF5272_FEC_INTERRUPT_MASK);
376 put_reg(MCF5272_SIM->enet.ecr, MCF5272_FEC_ECR_ETHER_EN);
378 /* Indicate that there have been empty receive buffers produced. */
380 put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
383 /* Set the flag to indicate that the device is up and running. */
385 PMCF5272_FEC_DATA(sc)->operational = ETH_DEV_UP;
389 /* A routine to halt the FEC. */
391 MCF5272_fec_stop(struct eth_drv_sc *sc)
394 /* Stop the packet transmission gracefully. */
396 /* Set the Graceful Transmit Stop bit. */
398 put_reg(MCF5272_SIM->enet.tcr, get_reg(MCF5272_SIM->enet.tcr)
399 | MCF5272_FEC_TCR_GTS);
401 /* Wait for the current transmission to complete. */
403 while( !(get_reg(MCF5272_SIM->enet.eir) & MCF5272_FEC_EIR_GRA));
405 /* Clear the GRA event. */
407 put_reg(MCF5272_SIM->enet.eir, MCF5272_FEC_EIR_GRA);
409 /* Disable all FEC interrupts by clearing the IMR register. */
411 put_reg(MCF5272_SIM->enet.eimr, 0);
413 /* Clear the GTS bit so frames can be tranmitted when restarted */
415 put_reg(MCF5272_SIM->enet.tcr, get_reg(MCF5272_SIM->enet.tcr) &
416 ~MCF5272_FEC_TCR_GTS);
418 /* Set the Ethernet control register to zero to disable the FEC. */
420 put_reg(MCF5272_SIM->enet.ecr, 0);
422 /* Deliver any pending frames and acknowledge any transmitted frames. */
424 MCF5272_fec_deliver(sc);
426 /* Set the flag to indicate that the device is down. */
428 PMCF5272_FEC_DATA(sc)->operational = ETH_DEV_DOWN;
432 /* This routine is called to perform special "control" opertions. */
435 MCF5272_fec_control(struct eth_drv_sc *sc, unsigned long key,
436 void *data, int data_length)
441 case ETH_DRV_SET_MAC_ADDRESS:
444 /* Set the hardware address of the Ethernet controller. */
446 struct ifreq* p_ifreq = data;
448 /* If the length of the strcutre is not equal to the size of */
449 /* ifreq, then exit with an error. */
451 if (data_length != sizeof(*p_ifreq))
456 /* Set the lower 4-byte address. */
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));
464 /* Set the upper 2-byte address. */
466 put_reg(MCF5272_SIM->enet.maur,
468 | (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[4] <<24)
469 | (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[5] <<16));
472 /* Return 1 to indicate that programming of the new MAC */
473 /* address is successful. */
482 case ETH_DRV_GET_IF_STATS:
483 case ETH_DRV_GET_IF_STATS_UD:
488 struct ether_drv_stats* pstats = (struct ether_drv_stats*)
490 MCF5272_FEC_DIAG diag;
492 /* Retrieve the driver defined diagnostic structure. */
493 MCF5272_get_stats(sc, &diag);
495 strcpy(pstats->description, ether_device_name);
496 pstats->duplex = ETH_MODE_UNKNWON;
497 pstats->operational = (unsigned char )PMCF5272_FEC_DATA(sc)->operational;
500 /* Translate the device specific diagnostic values to the */
501 /* generic ether_drv_stats values. */
503 /* Get the receive bytes count. */
504 pstats->rx_count = diag.rx_bytes_cnt;
506 /* Get the number of successful packet received. */
507 pstats->rx_good = diag.rx_pk_cnt;
509 /* Get the receive CRC error count. */
510 pstats->rx_crc_errors = diag.rx_crc_err_cnt;
512 /* Get the receive overrun error count. */
513 pstats->rx_overrun_errors = diag.rx_overrun_err_cnt;
515 /* Get the received short frame error count. */
516 pstats->rx_short_frames = diag.rx_short_frm_err_cnt;
518 /* Get the received long frame error count. */
519 pstats->rx_too_long_frames = diag.rx_long_frm_err_cnt;
521 /* Get the number of transmitted bytes. */
522 pstats->tx_count = diag.tx_bytes_cnt;
524 /* Get the number of defered packets. */
525 pstats->tx_deferred = diag.tx_def_cnt;
527 /* The number of successfully transmitted packets. */
528 pstats->tx_good = diag.tx_pk_cnt;
530 /* Get the transmit late collision count. */
531 pstats->tx_late_collisions = diag.tx_late_col_cnt;
533 /* Get the transmit underrun count. */
534 pstats->tx_underrun = diag.tx_underrun_cnt;
536 /* Get the transmit late collision count. */
537 pstats->tx_total_collisions = diag.tx_late_col_cnt;
543 /* Copy the ethernet name device over. */
545 strcpy(((struct mcf5272_ether_drv_stats*)data)->description,
549 MCF5272_get_stats(sc,
550 &((struct mcf5272_ether_drv_stats*)data)->stats);
552 /* Copy the mode over. */
554 ((struct mcf5272_ether_drv_stats*)data)->duplex =
555 PMCF5272_FEC_DATA(sc)->duplex;
557 /* The ethernet driver is operational. */
559 ((struct mcf5272_ether_drv_stats*)data)->operational =
560 PMCF5272_FEC_DATA(sc)->operational;
562 /* Copy the speed over. */
564 ((struct mcf5272_ether_drv_stats*)data)->speed =
565 PMCF5272_FEC_DATA(sc)->speed;
573 #endif /* CYGPKG_NET */
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 */
587 MCF5272_fec_can_send(struct eth_drv_sc *sc)
589 const int buffer_window = 5; /* Specifies the minimum empty buffer descrpitors */
591 if ((NUM_TXBDS - PBUF_INFO(sc)->num_busy_bd) > buffer_window)
597 PMCF5272_FEC_DATA(sc)->diag_counters.tx_full_cnt++;
603 /* This routine is called by eCos to send a frame to the ethernet */
607 MCF5272_fec_send(struct eth_drv_sc *sc,
608 struct eth_drv_sg *sg_list,
614 /* Call eth_tx_check() routine for any packet transmitted by eCos. */
616 eth_tx_check(sg_list, sg_len);
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. */
624 if (NUM_TXBDS - PBUF_INFO(sc)->num_busy_bd > sg_len)
626 MCF5272_fec_common_send(sc, sg_list, sg_len, total_len, key, TX_KEY_ECOS);
633 CYG_ASSERT(false, "ETH: Send buffer full");
635 /* Inform the upper layer of a completion of the packet. */
637 (sc->funs->eth_drv->tx_done)(sc,
644 /* This routine is called to send a frame to the ethernet controller. */
645 /* This is a generic send routine. */
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.
658 MCF5272_fec_common_send(struct eth_drv_sc *sc,
659 struct eth_drv_sg *sg_list,
663 tx_key_type_t key_type)
668 buf_info_t* p_buf = PBUF_INFO(sc);
671 CYG_ASSERT(sg_len > 0, "ETH: sg_len cannot be zero");
674 /* Update the number of used transmitted buffer desciptors. */
676 p_buf->num_busy_bd += sg_len;
678 /* Keep track of the maximum number of busy transmit buffer */
681 if (p_buf->num_busy_bd > p_buf->max_num_busy_bd)
683 p_buf->max_num_busy_bd = p_buf->num_busy_bd;
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. */
690 nbuf_enq_tx_key(p_buf, (p_buf->iTxbd + sg_len - 1) % NUM_TXBDS,
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. */
701 first_bd = pBD = nbuf_tx_allocate(p_buf);
706 CYG_ASSERT(pBD != NULL, "ETH: nbuf_tx_allocate() returned NULL");
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. */
713 pBD->data = (uint8*)sg_list[i].buf;
714 pBD->length = sg_list[i].len;
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 */
724 pBD->status |= TX_BD_L | TX_BD_TC | TX_BD_R;
726 /* When we have reached the last buffer scatther list, we */
727 /* break from the loop. */
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. */
743 pBD->status |= TX_BD_R;
747 /* Allocate the next buffer descriptor. */
749 pBD = nbuf_tx_allocate(p_buf);
753 /* Advance to the next index. */
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 */
764 first_bd->status |= TX_BD_R;
766 /* Indicate that there is a transmit buffer ready. */
768 put_reg(MCF5272_SIM->enet.tdar, 1);
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. */
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. */
785 MCF5272_fec_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
787 uint_t fill_count = 0, buf_count;
788 uint_t frame_length = 0, buf_len;
790 cyg_uint8* buf = NULL;
791 cyg_bool_t done = false;
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. */
799 buf = (cyg_uint8*)sg_list[0].buf;
805 /* Get the next buffer descriptor (bd). */
807 pNbuf = nbuf_rx_get_next(PBUF_INFO(sc));
809 CYG_ASSERT(pNbuf != NULL, "Cannot get the next bd");
811 if (pNbuf->status & TX_BD_L)
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. */
819 buf_len = (uint_t)pNbuf->length - frame_length;
821 /* Since the last bd, set done to true in order to exit the */
828 buf_len = RX_BUFFER_SIZE;
830 /* Update the frame length. */
832 frame_length += RX_BUFFER_SIZE;
836 /* Copy the packet to the scatter gather list if there is a buffer */
837 /* to copy the packet to. */
839 for (buf_count = 0; buf_count < buf_len && buf != NULL;)
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. */
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));
853 /* Copy the buffer to the upper layer driver buffer. */
855 memcpy(&buf[fill_count],
856 &pNbuf->data[buf_count],
859 /* Update the counts to reflect the number of bytes copied. */
861 fill_count += copy_len;
862 buf_count += copy_len;
864 /* If the buffer in the scatter-gather list is full, we */
865 /* attempt to retrieve the next buffer in the list. */
867 if (fill_count >= sg_list[sg_index].len)
870 /* If there is no more buffer, set the buf to NULL and */
873 if (++sg_index >= sg_len)
880 buf = (cyg_uint8*)sg_list[sg_index].buf;
887 /* Release the buffer scriotor so it cab be used to receive other */
890 nbuf_rx_release(pNbuf);
892 }while(done == false);
894 /* Notify the FEC that there are receive buffer descriptors available */
897 put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
900 /*******************************************************************************
901 MCF5252_fec_recv_handler() - Receive handler to read the received
902 buffer descriptors and inform the upper layer driver of the arrival
906 bool MCF5252_fec_recv_handler(struct eth_drv_sc * sc)
909 /* Receive interrupt has occurred informing driver that a frame has */
910 /* been written to the buffer. */
913 buf_info_t* p_buf_info = PBUF_INFO(sc);
914 MCF5272_fec_priv_data_t* eth_data = PMCF5272_FEC_DATA(sc);
917 /* Pointer to the first buffer descriptor. */
921 /* Check to see if the buffer descrpitor is not busy. */
923 if (nbuf_rx_next_ready(p_buf_info))
926 /* Flag that indicates whether the buffer is wrapped. */
928 cyg_bool_t wrap = false;
930 /* Get the index of the buffer desrciptor of the next frame. */
932 uint_t index = nbuf_rx_get_index(p_buf_info);
933 cyg_bool_t error = false;
936 /* Get the pointer to the first buffer descriptor. */
938 p_first_bd = nbuf_rx_get(p_buf_info, index);
942 pNBuf = nbuf_rx_get(p_buf_info, index);
944 if (pNBuf->status & RX_BD_E)
947 /* The buffer is empty or the FEC is stll writing to the */
948 /* buffer. then exit. */
954 /* Advance the index to the next buffer descriptor in the */
957 index = (index + 1) % NUM_RXBDS;
959 if ((pNBuf->status & (RX_BD_L | RX_BD_W)) == RX_BD_W)
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. */
970 if (pNBuf->status & RX_BD_TR)
973 /* Packet truncate count. */
975 eth_data->diag_counters.rx_trunc_error_cnt++;
977 /* Release the bds. */
979 nbuf_rx_release_pkt(p_buf_info);
981 /* Update the receive error count. */
983 eth_data->diag_counters.rx_err_cnt++;
985 /* Notify the FEC that there are receive buffer */
986 /* descriptors available from the FEC. */
988 put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
994 if (pNBuf->status & RX_BD_L)
997 /* Get the length of frame contain in the buffers. */
1001 /* If there is an error in receiving the packet, we */
1002 /* proceed to update the counters. Otherwise, we just fall */
1005 if (pNBuf->status & (RX_BD_LG | RX_BD_SH | RX_BD_CR |
1009 /* Update the diagnostic counters. */
1011 if (pNBuf->status & RX_BD_LG)
1013 /* Larget frame error count. */
1014 eth_data->diag_counters.rx_long_frm_err_cnt++;
1017 if (pNBuf->status & RX_BD_SH)
1019 /* Short frame error count. */
1020 eth_data->diag_counters.rx_short_frm_err_cnt++;
1023 if (pNBuf->status & RX_BD_CR)
1025 /* CRC error count. */
1026 eth_data->diag_counters.rx_crc_err_cnt++;
1029 if (pNBuf->status & RX_BD_OV)
1031 /* Overrun error count. */
1032 eth_data->diag_counters.rx_overrun_err_cnt++;
1035 /* Release the packet. */
1037 nbuf_rx_release_pkt(p_buf_info);
1039 /* Update the receive error count. */
1041 eth_data->diag_counters.rx_err_cnt++;
1043 /* Notify the FEC that there are receive buffer */
1044 /* descriptors available for the FEC */
1046 put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
1048 /* Set the error flag to true to indicate that there */
1055 }while(!(pNBuf->status & RX_BD_L));
1059 cyg_uint8* buf_ptr = p_first_bd->data;
1061 /* Since there is no error, we update the good statistic */
1064 /* Update the number of frames received. */
1066 eth_data->diag_counters.rx_pk_cnt++;
1068 /* Update the number of bytes in the frame received. */
1070 /* Subract 4 bytes from the length because the packet */
1071 /* includes the 4-byte FCS. */
1073 eth_data->diag_counters.rx_bytes_cnt += (len - 4);
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. */
1083 uint_t count_len = 0;
1086 /* Set p_buf the pointer to temporary packet biffer which */
1087 /* we will use to copy the packet. */
1089 u8_t* p_buf = (u8_t*)ð_data->pkt_buf;
1091 /* Get the index of the buffer desrcitor of the next frame. */
1093 uint_t index = nbuf_rx_get_index(p_buf_info);
1098 /* Get the buffer descriptor. */
1100 pNBuf = nbuf_rx_get(p_buf_info, index);
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. */
1109 if (pNBuf->status & RX_BD_L)
1111 pk_len = len - count_len;
1115 pk_len = RX_BUFFER_SIZE;
1118 /* Copy the content of the buffer to the temporary */
1119 /* packet buffer. */
1121 memcpy(&p_buf[count_len], pNBuf->data, pk_len);
1124 /* Keep count of the number of bytes read from the */
1125 /* buffer descriptor. */
1127 count_len += pk_len;
1129 /* Advance to the to next buffer descriptor. */
1131 index = (index + 1) % NUM_RXBDS;
1133 }while(!(pNBuf->status & RX_BD_L));
1135 buf_ptr = (u8_t*)ð_data->pkt_buf;
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. */
1144 if (!eth_rx_pkt_filter(buf_ptr, len))
1147 /* Inform the upper layer of a complete packet. */
1149 (sc->funs->eth_drv->recv)(sc, len);
1154 /* Release the buffer descriptors. */
1156 nbuf_rx_release_good_pkt(p_buf_info);
1159 /* Notify the FEC that there is at least a receive buffer */
1160 /* descriptos available for the FEC. */
1162 put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
1172 /* Indicates that there are no more receive packets. */
1179 /*******************************************************************************
1180 MCF5272_fec_transmit_handler() - Transmit handler informs the upper
1181 layer packet of a completion of a transmit packet.
1185 bool MCF5272_fec_transmit_handler(struct eth_drv_sc * sc)
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. */
1192 /* Check to see which frame has completed sending so we can tell the */
1193 /* upper layer to free up ts buffer. */
1195 buf_info_t* p_buf_info = PBUF_INFO(sc);
1196 MCF5272_fec_priv_data_t* eth_data = PMCF5272_FEC_DATA(sc);
1199 tx_keys_t key_entry;
1204 /* Check wether there is any pending transmit buffer descriptors that */
1205 /* are to deallocated. */
1207 if ((index = nbuf_peek_tx_key(p_buf_info)) != -1)
1210 /* Get the pointer to the buffer descriptor so that the flags in */
1211 /* the status word in the buffer descriptor can be examined. */
1213 NBUF* pNbuf = nbuf_tx_get(p_buf_info, index);
1215 CYG_ASSERT(pNbuf->status & TX_BD_L, "Index to BD is not the last BD");
1217 if (pNbuf->status & TX_BD_R)
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. */
1225 if ((next_bd = nbuf_peek_bd_ahead(p_buf_info)))
1227 if (!(next_bd->status & TX_BD_R) &&
1228 pNbuf->status & TX_BD_R)
1231 eth_data->diag_counters.tx_not_complete_cnt++;
1237 /* If the buffer not ready we return immediatly. */
1245 /* Dequeue the packet from the trasnmt packet queue to indicate */
1246 /* that the packet is not being transmitted by the FEC. */
1248 nbuf_deq_tx_key(p_buf_info, &key_entry);
1250 /* Release the used buffers. */
1252 for ( i = 0; i < key_entry.num_dbufs; i++)
1256 /* Get the BD based on the index. */
1258 pNbd = nbuf_tx_get(p_buf_info,
1259 (key_entry.start_index + i) % NUM_TXBDS);
1261 /* The last buffer descriptor of the packet. */
1263 if (pNbd->status & TX_BD_L)
1266 if (pNbd->status & TX_BD_RL)
1269 /* Update the number of retries. */
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++;
1278 /* Check for error status. If there is an error */
1279 /* proceed the increment the appropriate statistic */
1282 if (pNbd->status & (TX_BD_UN |
1288 if (pNbd->status & TX_BD_HB)
1291 /* Heartbeat error count. */
1293 eth_data->diag_counters.tx_hb_err_cnt++;
1296 if (pNbd->status & TX_BD_UN)
1299 /* Transmit underrun error count. */
1301 eth_data->diag_counters.tx_underrun_cnt++;
1304 if (pNbd->status & TX_BD_CSL)
1307 /* Transmit carrier loss count. */
1309 eth_data->diag_counters.tx_carrrier_loss_cnt++;
1312 if (pNbd->status & TX_BD_LC)
1315 /* Update the late collision counter. */
1317 eth_data->diag_counters.tx_late_col_cnt++;
1320 /* Update the number transmit error count. */
1322 eth_data->diag_counters.tx_err_cnt++;
1326 /* Update the diagnostic counters */
1328 if (pNbd->status & TX_BD_DEF)
1330 /* Defer indication count. */
1331 eth_data->diag_counters.tx_def_cnt++;
1334 /* Update the number of transmitted packets. */
1336 eth_data->diag_counters.tx_pk_cnt++;
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. */
1345 eth_data->diag_counters.tx_bytes_cnt +=
1346 key_entry.pk_len < ETH_MIN_SIZE ? ETH_MIN_SIZE :
1350 /* Get the number of retries. */
1352 eth_data->diag_counters.tx_retry_cnt +=
1353 (pNbd->status >> 2) & 0xF;
1358 /* Release the buffer descriptor so that it can be reused to */
1359 /* transmit the next packet. */
1361 nbuf_tx_release(pNbd);
1363 /* If the start_index is the same as the index to the last */
1364 /* buffer descriptor, then quit the loop. */
1368 /* Decrement the number of busy descriptors. */
1370 p_buf_info->num_busy_bd -= key_entry.num_dbufs;
1372 switch(key_entry.key_type)
1376 /* Inform the upper layer of a completion of the packet. */
1378 (sc->funs->eth_drv->tx_done)(sc,
1384 /* Inform the application of the completion of the packet. */
1386 eth_send_done(key_entry.tx_key);
1394 /* Retrun false to indicate that the transmit buffer is empty. */
1399 /* Indicate that the packet at the transmit buffer has been */
1400 /* successfully handled. */
1406 /* This routine informs the upper layer of a completion of a sent */
1407 /* frame and a reception of a frame. */
1410 MCF5272_fec_deliver(struct eth_drv_sc * sc)
1415 /* Clear the event register. */
1417 put_reg(MCF5272_SIM->enet.eir,
1418 (event = (get_reg(MCF5272_SIM->enet.eir) &
1419 MCF5272_FEC_INTERRUPT_MASK)));
1421 while(event & MCF5272_FEC_INTERRUPT_MASK)
1424 /* This flag will specifies whether we need to service the */
1425 /* transmit or receive sides of the Ethernet controller. */
1430 /* Keep count of any bus error that might occur when the FEC */
1431 /* attempts while the FEC accessing the internal bus. */
1433 if (event & MCF5272_FEC_EIR_EBERR)
1435 PMCF5272_FEC_DATA(sc)->diag_counters.internal_bus_error_cnt++;
1440 packet_status = false;
1442 /* Call receive the handler to receive packets. */
1444 packet_status |= MCF5252_fec_recv_handler(sc);
1446 /* Call transit the handed to release the transmit buffers. */
1448 packet_status |= MCF5272_fec_transmit_handler(sc);
1450 /* Loop back up until all the receive and transmit buffers */
1453 }while(packet_status);
1455 /* Retrieve the next interrupt event. */
1457 /* Clear the event register. */
1459 put_reg(MCF5272_SIM->enet.eir,
1460 event = (get_reg(MCF5272_SIM->enet.eir) &
1461 MCF5272_FEC_INTERRUPT_MASK));
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. */
1470 /* Allow interrupts by setting IMR register. */
1472 put_reg(MCF5272_SIM->enet.eimr, get_reg(MCF5272_SIM->enet.eimr) |
1473 MCF5272_FEC_INTERRUPT_MASK
1478 /* Generic Interrupt Service Routine. This routine wakes up the DSR */
1479 /* for further processing. */
1482 MCF5272_fec_isr(cyg_vector_t vector, cyg_addrword_t data,
1483 HAL_SavedRegisters *regs)
1486 /* Mask the FEC's interrupts so that it won't generate these */
1487 /* interrupts anymore as the driver reads the packets or acknowledges */
1490 put_reg(MCF5272_SIM->enet.eimr, get_reg(MCF5272_SIM->enet.eimr) &
1491 ~(MCF5272_FEC_INTERRUPT_MASK));
1493 return CYG_ISR_CALL_DSR;
1497 /* Call MCF5272_fec_deliver() to poll the FEC. */
1500 MCF5272_fec_int(struct eth_drv_sc *sc)
1502 MCF5272_fec_deliver(sc);
1506 MCF5272_fec_int_vector(struct eth_drv_sc *sc)
1509 /* How do you return multiple interrupt vector? */
1511 return CYGNUM_HAL_VECTOR_ERX;
1514 /* This routine updates the Ethernet statistics counters. This method */
1515 /* is called by eCos every second. */
1517 static void one_second_alarm_func(cyg_handle_t alarm, cyg_addrword_t data)
1519 #define WRAP_SUBTRACT(_VAL1_,_VAL2_) \
1520 ({unsigned long val;if (_VAL1_ >= _VAL2_) val = _VAL1_ - _VAL2_; \
1521 else val=(0-_VAL2_)+_VAL1_; val;})
1523 ((MCF5272_fec_priv_data_t*)data)->diag_counters.rx_bytes_cnt_sec =
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);
1528 ((MCF5272_fec_priv_data_t*)data)->diag_counters.tx_bytes_cnt_sec =
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);
1533 ((MCF5272_fec_priv_data_t*)data)->diag_counters.rx_pk_cnt_sec =
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);
1538 ((MCF5272_fec_priv_data_t*)data)->diag_counters.tx_pk_cnt_sec =
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);
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;
1554 /* Retrieve the stats information. */
1556 void MCF5272_get_stats(struct eth_drv_sc *sc, MCF5272_FEC_DIAG* stats)
1558 memcpy(stats, &PMCF5272_FEC_DATA(sc)->diag_counters,
1559 sizeof (MCF5272_FEC_DIAG));
1561 /* Retrieve the number of available buffer descriptors and the */
1562 /* minimum value. */
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;
1571 /*****************************************************************************
1573 The following functions provide an interface directly to the
1574 ethernet driver for applications that wish to circumvent the IP stack.
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.
1580 *****************************************************************************/
1582 /*****************************************************************************
1583 eth_rx_pkt_filter -- Ethernet receive packet filter
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.
1589 We declare it weak so that other routine can override it.
1593 pkt: Pointer to the packet.
1595 pkt_len: The length of the packet including all headers, the 32-bit
1596 Ethernet CRC, and any Ethernet frame padding.
1602 true: Do not send the packet to the IP stack.
1604 false: Send the packet to the IP stack.
1606 *****************************************************************************/
1607 int_t eth_rx_pkt_filter(u8_t * pkt, uint_t pkt_len)
1610 /* Always return false by default. */
1615 /*****************************************************************************
1616 eth_tx_check -- Watch transmitting Ethernet packets
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.
1622 We declare it weak so that other routine can override it.
1626 sg_list: Pointer to the scatter-gather list.
1628 sg_len: The number of scatter-gather entries in the list.
1636 *****************************************************************************/
1637 void eth_tx_check(struct eth_drv_sg * sg_list, unsigned int sg_len)
1640 /* Do nothing by default. */
1644 /*****************************************************************************
1645 eth_send -- Transmit a raw Ethernet packet
1647 This function sends a packet to the Ethernet controller thus
1648 passing the eCos IP stack.
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()
1656 sg_list: Pointer to the scatter-gather list to send.
1658 sg_len: The size of the scatter-gather list.
1660 tag: A value that we pass as a parameter to eth_send_done()
1661 function when the FEC has completed sending the packet.
1667 true: if the packet is successfully queued to the device driver's
1670 false : If the routine fails to send the packet.
1672 *****************************************************************************/
1673 int_t eth_send(struct eth_drv_sg* sg_list, unsigned int sg_len,
1680 s = cyg_splsoftnet();
1682 /* If there is enough buffer descriptors, then send the packet. */
1683 /* Otherwise, throw the packet away and return a false value. */
1685 if (NUM_TXBDS - PBUF_INFO(&MCF5272_fec_sc)->num_busy_bd > sg_len)
1688 /* Call the common send routine to send the packet. */
1690 MCF5272_fec_common_send(&MCF5272_fec_sc,
1702 /* Fail to send the packet. */
1707 /* Release the Ethernet driver lock. */
1714 /*****************************************************************************
1715 eth_send_done -- eth_send callback
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.
1721 We declare it weak so that other routine can override it.
1725 tag: A value that we pass as a parameter to eth_send_done()
1726 function when the FEC has completed sending the packet.
1734 *****************************************************************************/
1735 void eth_send_done(unsigned long tag)
1744 /* Defined Ethernet Frame Types */
1745 #define FRAME_IP (0x0800)
1746 #define FRAME_ARP (0x0806)
1747 #define FRAME_RARP (0x8035)
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
1753 /* Assign a protocol number for the loop test */
1754 static uint16 eth_type = 0x0300;
1756 /* Global variable containing length of data to transmit */
1757 static uint16 data_length = 512;
1759 /* Transmit data size of each transmti buffer descriptor. */
1761 #define TX_BUFFER_SIZE (576) /* must be divisible by 16 */
1765 fec_start_loopback_test(void)
1767 /* Initalize the buffer descriptors. */
1769 nbuf_init(&MCF5272_fec_priv_data.nbuffer);
1771 /* Initalize the Ethernet controllder device. */
1773 MCF5272_fec_init(&MCF5272_fec_netdev);
1778 /********************************************************************/
1780 loop_fill_buffers(void)
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];
1787 uint_t data_length = TX_BUFFER_SIZE;
1789 for (i = 0; i < NUM_TXBDS; i++)
1792 MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data = output_buffer[i];
1795 /* Load buffers 0 through 3 with a single data patterns */
1797 memset(&MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[ETH_HDR_SIZE],0x55,data_length);
1800 memset(&MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[ETH_HDR_SIZE],0xAA,data_length);
1803 memset(&MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[ETH_HDR_SIZE],0x00,data_length);
1806 memset(&MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[ETH_HDR_SIZE],0xFF,data_length);
1809 /* Buffer[4]: Load increasing walking ones */
1812 for (index = 0; index < data_length; index++)
1814 if (pattern == 0x0100)
1816 MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[index] = (uint8)pattern;
1821 /* Buffer[5]: Load decreasing walking ones */
1824 for (index = 0; index < data_length; index++)
1826 if (pattern == 0x00)
1828 MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[index] = (uint8)pattern;
1833 /* Buffer[6]: Load "Increment from 0" pattern */
1835 for (index = 0; index < data_length; index++)
1836 MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[index] = (uint8) ((index-14)%256);
1839 /* Buffer[7]: Load "Decrement from 255" pattern */
1841 for (index = 0; index < data_length; index++)
1842 MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[index] = (uint8)(255- ((index-14)%256));
1848 /********************************************************************/
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. */
1861 /* Compare what I received to what I transmitted */
1862 for (i = 0; i < (data_length + ETH_HDR_SIZE); i++)
1864 if (TxBuffer[fec_nif->f_rx % NUM_TXBDS].data[i] != pNbuf->data[i])
1866 /* Increment reception error count */
1867 fec_nif->f_rx_err++;
1871 /* Increment reception count */
1874 /* Update progress indicator */
1875 if (!(fec_nif->f_rx % 200))
1877 ihash = (ihash + 1) % 4;
1878 diag_printf("\b%c",hash[ihash]);