source: rtems/c/src/lib/libbsp/m68k/uC5282/network/network.c @ dd2f891

4.104.114.84.9
Last change on this file since dd2f891 was dd2f891, checked in by Eric Norum <WENorum@…>, on Feb 2, 2005 at 2:17:11 PM

Provide 'last-ditch' hardware address.

  • Property mode set to 100644
File size: 25.4 KB
Line 
1/*
2 * RTEMS/TCPIP driver for MCF5282 Fast Ethernet Controller
3 *
4 * TO DO: MII communications to set speed, full/half duplex, etc.
5 * TO DO: Check network stack code -- force longword alignment of all tx mbufs?
6 */
7
8#include <bsp.h>
9#include <stdio.h>
10#include <errno.h>
11#include <stdarg.h>
12#include <string.h>
13#include <rtems.h>
14#include <rtems/error.h>
15#include <rtems/rtems_bsdnet.h>
16
17#include <sys/param.h>
18#include <sys/mbuf.h>
19#include <sys/socket.h>
20#include <sys/sockio.h>
21
22#include <net/ethernet.h>
23#include <net/if.h>
24
25#include <netinet/in.h>
26#include <netinet/if_ether.h>
27
28
29/*
30 * Number of interfaces supported by this driver
31 */
32#define NIFACES 1
33
34#define FEC_INTC0_TX_VECTOR (64+23)
35#define FEC_INTC0_RX_VECTOR (64+27)
36
37/*
38 * Default number of buffer descriptors set aside for this driver.
39 * The number of transmit buffer descriptors has to be quite large
40 * since a single frame often uses three or more buffer descriptors.
41 */
42#define RX_BUF_COUNT     32
43#define TX_BUF_COUNT     20
44#define TX_BD_PER_BUF    3
45
46#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255")
47
48/*
49 * RTEMS event used by interrupt handler to signal daemons.
50 * This must *not* be the same event used by the TCP/IP task synchronization.
51 */
52#define TX_INTERRUPT_EVENT RTEMS_EVENT_1
53#define RX_INTERRUPT_EVENT RTEMS_EVENT_1
54
55/*
56 * RTEMS event used to start transmit daemon.
57 * This must not be the same as INTERRUPT_EVENT.
58 */
59#define START_TRANSMIT_EVENT RTEMS_EVENT_2
60
61/*
62 * Receive buffer size -- Allow for a full ethernet packet plus CRC (1518).
63 * Round off to nearest multiple of RBUF_ALIGN.
64 */
65#define MAX_MTU_SIZE    1518
66#define RBUF_ALIGN      4
67#define RBUF_SIZE       ((MAX_MTU_SIZE + RBUF_ALIGN) & ~RBUF_ALIGN)
68
69#if (MCLBYTES < RBUF_SIZE)
70    #error "Driver must have MCLBYTES > RBUF_SIZE"
71#endif
72
73typedef struct mcf5282BufferDescriptor_ {
74    volatile rtems_unsigned16   status;
75    rtems_unsigned16            length;
76    volatile void               *buffer;
77} mcf5282BufferDescriptor_t;
78
79/*
80 * Per-device data
81 */
82struct mcf5282_enet_struct {
83    struct arpcom               arpcom;
84    struct mbuf                 **rxMbuf;
85    struct mbuf                 **txMbuf;
86    int                         acceptBroadcast;
87    int                         rxBdCount;
88    int                         txBdCount;
89    int                         txBdHead;
90    int                         txBdTail;
91    int                         txBdActiveCount;
92    mcf5282BufferDescriptor_t  *rxBdBase;
93    mcf5282BufferDescriptor_t  *txBdBase;
94    rtems_id                    rxDaemonTid;
95    rtems_id                    txDaemonTid;
96
97    /*
98     * Statistics
99     */
100    unsigned long   rxInterrupts;
101    unsigned long   txInterrupts;
102    unsigned long   txRawWait;
103    unsigned long   txRealign;
104};
105static struct mcf5282_enet_struct enet_driver[NIFACES];
106
107static rtems_isr
108mcf5282_fec_rx_interrupt_handler( rtems_vector_number v )
109{
110    MCF5282_FEC_EIR = MCF5282_FEC_EIR_RXF;
111    MCF5282_FEC_EIMR &= ~MCF5282_FEC_EIMR_RXF;   
112    enet_driver[0].rxInterrupts++;
113    rtems_event_send(enet_driver[0].rxDaemonTid, RX_INTERRUPT_EVENT);
114}
115
116static rtems_isr
117mcf5282_fec_tx_interrupt_handler( rtems_vector_number v )
118{
119    MCF5282_FEC_EIR = MCF5282_FEC_EIR_TXF;
120    MCF5282_FEC_EIMR &= ~MCF5282_FEC_EIMR_TXF;   
121    enet_driver[0].txInterrupts++;
122    rtems_event_send(enet_driver[0].txDaemonTid, TX_INTERRUPT_EVENT);
123}
124
125/*
126 * Allocate buffer descriptors from (non-cached) on-chip static RAM
127 * Ensure 128-bit (16-byte) alignment
128 */
129static mcf5282BufferDescriptor_t *
130mcf5282_bd_allocate(unsigned int count)
131{
132    extern char __SRAMBASE[];
133    static mcf5282BufferDescriptor_t *bdp = (mcf5282BufferDescriptor_t *)__SRAMBASE;
134    mcf5282BufferDescriptor_t *p = bdp;
135
136    bdp += count;
137    if ((int)bdp & 0xF)
138        bdp = (mcf5282BufferDescriptor_t *)((char *)bdp + (16 - ((int)bdp & 0xF)));
139    return p;
140}
141
142static void
143mcf5282_fec_initialize_hardware(struct mcf5282_enet_struct *sc)
144{
145    int i;
146    unsigned char *hwaddr;
147    rtems_status_code status;
148    rtems_isr_entry old_handler;
149        unsigned32 clock_speed = get_CPU_clock_speed();
150
151/*  extern struct rtems_bsdnet_ifconfig netdriver_config; */
152
153
154    /*
155     * Issue reset to FEC
156     */
157    MCF5282_FEC_ECR = MCF5282_FEC_ECR_RESET;
158    rtems_task_wake_after(1);
159    /*
160     * Configuration of I/O ports is done outside of this function
161     */
162#if 0
163    imm->gpio.pbcnt |= MCF5282_GPIO_PBCNT_SET_FEC;        /* Set up port b FEC pins */
164#endif
165
166    /*
167     * Set our physical address
168     */
169    hwaddr = sc->arpcom.ac_enaddr;
170    MCF5282_FEC_PALR = (hwaddr[0] << 24) | (hwaddr[1] << 16) |
171                       (hwaddr[2] << 8)  | (hwaddr[3] << 0);
172    MCF5282_FEC_PAUR = (hwaddr[4] << 24) | (hwaddr[5] << 16);
173
174
175    /*
176     * Clear the hash table
177     */
178    MCF5282_FEC_GAUR = 0;
179    MCF5282_FEC_GALR = 0;
180
181    /*
182     * Set up receive buffer size
183     */
184    MCF5282_FEC_EMRBR = 1520; /* Standard Ethernet */
185
186    /*
187     * Allocate mbuf pointers
188     */
189    sc->rxMbuf = malloc(sc->rxBdCount * sizeof *sc->rxMbuf, M_MBUF, M_NOWAIT);
190    sc->txMbuf = malloc(sc->txBdCount * sizeof *sc->txMbuf, M_MBUF, M_NOWAIT);
191    if (!sc->rxMbuf || !sc->txMbuf)
192        rtems_panic("No memory for mbuf pointers");
193
194    /*
195     * Set receiver and transmitter buffer descriptor bases
196     */
197    sc->rxBdBase = mcf5282_bd_allocate(sc->rxBdCount);
198    sc->txBdBase = mcf5282_bd_allocate(sc->txBdCount);
199    MCF5282_FEC_ERDSR = (int)sc->rxBdBase;
200    MCF5282_FEC_ETDSR = (int)sc->txBdBase;
201
202    /*
203     * Set up Receive Control Register:
204     *   Not promiscuous
205     *   MII mode
206     *   Half duplex
207     *   No loopback
208     */
209    MCF5282_FEC_RCR = MCF5282_FEC_RCR_MAX_FL(MAX_MTU_SIZE) | 
210                      MCF5282_FEC_RCR_MII_MODE             |
211                      MCF5282_FEC_RCR_DRT;
212
213    /*
214     * Set up Transmit Control Register:
215     *   Half duplex
216     *   No heartbeat
217     */
218    MCF5282_FEC_TCR = 0;
219
220    /*
221     * Initialize statistic counters
222     */
223    MCF5282_FEC_MIBC = MCF5282_FEC_MIBC_MIB_DISABLE;
224    {
225    vuint32 *vuip = &MCF5282_FEC_RMON_T_DROP;
226    while (vuip <= &MCF5282_FEC_IEEE_R_OCTETS_OK)
227        *vuip++ = 0;
228    }
229    MCF5282_FEC_MIBC = 0;
230
231    /*
232     * Set MII speed to <2.5 MHz
233     */
234    if (clock_speed <= 25000000)
235        MCF5282_FEC_MSCR = MCF5282_FEC_MSCR_MII_SPEED(0x5);
236    else if (clock_speed <= 33000000)
237        MCF5282_FEC_MSCR = MCF5282_FEC_MSCR_MII_SPEED(0x7);
238    else if (clock_speed <= 40000000)
239        MCF5282_FEC_MSCR = MCF5282_FEC_MSCR_MII_SPEED(0x8);
240    else if (clock_speed <= 50000000)
241        MCF5282_FEC_MSCR = MCF5282_FEC_MSCR_MII_SPEED(0xA);
242    else if (clock_speed <= 66000000)
243        MCF5282_FEC_MSCR = MCF5282_FEC_MSCR_MII_SPEED(0xD);
244    else
245        MCF5282_FEC_MSCR = MCF5282_FEC_MSCR_MII_SPEED(0xF);
246
247    /*
248     * Set up receive buffer descriptors
249     */
250    for (i = 0 ; i < sc->rxBdCount ; i++)
251        (sc->rxBdBase + i)->status = 0;
252
253    /*
254     * Set up transmit buffer descriptors
255     */
256    for (i = 0 ; i < sc->txBdCount ; i++) {
257        sc->txBdBase[i].status = 0;
258        sc->txMbuf[i] = NULL;
259    }
260    sc->txBdHead = sc->txBdTail = 0;
261    sc->txBdActiveCount = 0;
262
263    /*
264     * Set up interrupts
265     */
266    status = rtems_interrupt_catch( mcf5282_fec_tx_interrupt_handler, FEC_INTC0_TX_VECTOR, &old_handler );
267    if (status != RTEMS_SUCCESSFUL)
268        rtems_panic ("Can't attach MCF5282 FEC TX interrupt handler: %s\n",
269                     rtems_status_text(status));
270    status = rtems_interrupt_catch(mcf5282_fec_rx_interrupt_handler, FEC_INTC0_RX_VECTOR, &old_handler);
271    if (status != RTEMS_SUCCESSFUL)
272        rtems_panic ("Can't attach MCF5282 FEC RX interrupt handler: %s\n",
273                     rtems_status_text(status));
274    MCF5282_INTC0_ICR23 = MCF5282_INTC_ICR_IL(FEC_IRQ_LEVEL) |
275                          MCF5282_INTC_ICR_IP(FEC_IRQ_TX_PRIORITY);
276    MCF5282_INTC0_IMRL &= ~(MCF5282_INTC_IMRL_INT23 | MCF5282_INTC_IMRL_MASKALL);
277    MCF5282_INTC0_ICR27 = MCF5282_INTC_ICR_IL(FEC_IRQ_LEVEL) |
278                          MCF5282_INTC_ICR_IP(FEC_IRQ_RX_PRIORITY);
279    MCF5282_INTC0_IMRL &= ~(MCF5282_INTC_IMRL_INT27 | MCF5282_INTC_IMRL_MASKALL);
280}
281
282/*
283 * Soak up buffer descriptors that have been sent.
284 */
285static void
286fec_retire_tx_bd(volatile struct mcf5282_enet_struct *sc )
287{
288    struct mbuf *m, *n;
289
290    while ((sc->txBdActiveCount != 0)
291        && ((sc->txBdBase[sc->txBdTail].status & MCF5282_FEC_TxBD_R) == 0)) {
292        m = sc->txMbuf[sc->txBdTail];
293        MFREE(m, n);
294        if (++sc->txBdTail == sc->txBdCount)
295            sc->txBdTail = 0;
296        sc->txBdActiveCount--;
297    }
298}
299
300static void
301fec_rxDaemon (void *arg)
302{
303    volatile struct mcf5282_enet_struct *sc = (volatile struct mcf5282_enet_struct *)arg;
304    struct ifnet *ifp = (struct ifnet* )&sc->arpcom.ac_if;
305    struct mbuf *m;
306    volatile rtems_unsigned16 status;
307    volatile mcf5282BufferDescriptor_t *rxBd;
308    int rxBdIndex;
309
310    /*
311     * Allocate space for incoming packets and start reception
312     */
313    for (rxBdIndex = 0 ; ;) {
314        rxBd = sc->rxBdBase + rxBdIndex;
315        MGETHDR(m, M_WAIT, MT_DATA);
316        MCLGET(m, M_WAIT);
317        m->m_pkthdr.rcvif = ifp;
318        sc->rxMbuf[rxBdIndex] = m;
319        rxBd->buffer = mtod(m, void *);
320        rxBd->status = MCF5282_FEC_RxBD_E;
321        if (++rxBdIndex == sc->rxBdCount) {
322            rxBd->status |= MCF5282_FEC_RxBD_W;
323            break;
324        }
325    }
326
327    /*
328     * Input packet handling loop
329     */
330    /* Indicate we have some ready buffers available */
331    MCF5282_FEC_RDAR = MCF5282_FEC_RDAR_R_DES_ACTIVE;
332
333    rxBdIndex = 0;
334    for (;;) {
335        rxBd = sc->rxBdBase + rxBdIndex;
336
337        /*
338         * Wait for packet if there's not one ready
339         */
340        if ((status = rxBd->status) & MCF5282_FEC_RxBD_E) {
341            /*
342             * Clear old events.
343             */
344            MCF5282_FEC_EIR = MCF5282_FEC_EIR_RXF;
345
346            /*
347             * Wait for packet to arrive.
348             * Check the buffer descriptor before waiting for the event.
349             * This catches the case when a packet arrives between the
350             * `if' above, and the clearing of the RXF bit in the EIR.
351             */
352            while ((status = rxBd->status) & MCF5282_FEC_RxBD_E) {
353                rtems_event_set events;
354                int level;
355
356                rtems_interrupt_disable(level);
357                MCF5282_FEC_EIMR |= MCF5282_FEC_EIMR_RXF;
358                rtems_interrupt_enable(level);
359                rtems_bsdnet_event_receive (RX_INTERRUPT_EVENT,
360                                            RTEMS_WAIT|RTEMS_EVENT_ANY,
361                                            RTEMS_NO_TIMEOUT,
362                                            &events);
363            }
364        }
365
366        /*
367         * Check that packet is valid
368         */
369        if (status & MCF5282_FEC_RxBD_L) {
370            /*
371             * Pass the packet up the chain.
372             * FIXME: Packet filtering hook could be done here.
373             */
374            struct ether_header *eh;
375            int len = rxBd->length - sizeof(rtems_unsigned32);;
376
377            /*
378             * Invalidate the cache and push the packet up.
379             * The cache is so small that it's more efficient to just
380             * invalidate the whole thing unless the packet is very small.
381             */
382            m = sc->rxMbuf[rxBdIndex];
383            if (len < 128)
384                rtems_cache_invalidate_multiple_data_lines(m->m_data, len);
385            else
386                rtems_cache_invalidate_entire_data();
387            m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header);
388            eh = mtod(m, struct ether_header *);
389            m->m_data += sizeof(struct ether_header);
390            ether_input(ifp, eh, m);
391
392            /*
393             * Allocate a new mbuf
394             */
395            MGETHDR(m, M_WAIT, MT_DATA);
396            MCLGET(m, M_WAIT);
397            m->m_pkthdr.rcvif = ifp;
398            sc->rxMbuf[rxBdIndex] = m;
399            rxBd->buffer = mtod(m, void *);
400        }
401
402        /*
403         * Reenable the buffer descriptor
404         */
405        rxBd->status = (status & MCF5282_FEC_RxBD_W) | MCF5282_FEC_RxBD_E;
406        MCF5282_FEC_RDAR = MCF5282_FEC_RDAR_R_DES_ACTIVE;
407
408        /*
409         * Move to next buffer descriptor
410         */
411        if (++rxBdIndex == sc->rxBdCount)
412            rxBdIndex = 0;
413    }
414}
415
416static void
417fec_sendpacket(struct ifnet *ifp, struct mbuf *m)
418{
419    struct mcf5282_enet_struct *sc = ifp->if_softc;
420    volatile mcf5282BufferDescriptor_t *firstTxBd, *txBd;
421    rtems_unsigned16 status;
422    int nAdded;
423
424   /*
425     * Free up buffer descriptors
426     */
427    fec_retire_tx_bd(sc);
428
429    /*
430     * Set up the transmit buffer descriptors.
431     * No need to pad out short packets since the
432     * hardware takes care of that automatically.
433     * No need to copy the packet to a contiguous buffer
434     * since the hardware is capable of scatter/gather DMA.
435     */
436    nAdded = 0;
437    firstTxBd = sc->txBdBase + sc->txBdHead;
438   
439    for (;;) {
440        /*
441         * Wait for buffer descriptor to become available
442         */
443        if ((sc->txBdActiveCount + nAdded)  == sc->txBdCount) {
444            /*
445             * Clear old events.
446             */
447            MCF5282_FEC_EIR = MCF5282_FEC_EIR_TXF;
448
449            /*
450             * Wait for buffer descriptor to become available.
451             * Check for buffer descriptors before waiting for the event.
452             * This catches the case when a buffer became available between
453             * the `if' above, and the clearing of the TXF bit in the EIR.
454             */
455            fec_retire_tx_bd(sc);
456            while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
457                rtems_event_set events;
458                int level;
459
460                rtems_interrupt_disable(level);
461                MCF5282_FEC_EIMR |= MCF5282_FEC_EIMR_TXF;   
462                rtems_interrupt_enable(level);
463                sc->txRawWait++;
464                rtems_bsdnet_event_receive(TX_INTERRUPT_EVENT,
465                                           RTEMS_WAIT|RTEMS_EVENT_ANY,
466                                           RTEMS_NO_TIMEOUT,
467                                           &events);
468                fec_retire_tx_bd(sc);
469            }
470        }
471   
472        /*
473         * Don't set the READY flag on the first fragment
474         * until the whole packet has been readied.
475         */
476        status = nAdded ? MCF5282_FEC_TxBD_R : 0;
477   
478        /*
479         * The IP fragmentation routine in ip_output
480         * can produce fragments with zero length.
481         */
482        txBd = sc->txBdBase + sc->txBdHead;
483        if (m->m_len) {
484            char *p = mtod(m, char *);
485            /*
486             * Stupid FEC can't handle misaligned data!
487             * Given the way that mbuf's are layed out it should be
488             * safe to shuffle the data down like this.....
489             * Perhaps this code could be improved with a "Duff's Device".
490             */
491            if ((int)p & 0x3) {
492                int l = m->m_len;
493                char *dest = p - ((int)p & 0x3);
494                unsigned16 *o = (unsigned16 *)dest, *i = (unsigned16 *)p;
495                while (l > 0) {
496                    *o++ = *i++;
497                    l -= sizeof(unsigned16);
498                }
499                p = dest;
500                sc->txRealign++;
501            }
502            txBd->buffer = p;
503            txBd->length = m->m_len;
504            sc->txMbuf[sc->txBdHead] = m;
505            nAdded++;
506            if (++sc->txBdHead == sc->txBdCount) {
507                status |= MCF5282_FEC_TxBD_W;
508                sc->txBdHead = 0;
509            }
510            m = m->m_next;
511        }
512        else {
513            /*
514             * Just toss empty mbufs
515             */
516            struct mbuf *n;
517            MFREE(m, n);
518            m = n;
519        }
520        if (m == NULL) {
521          if (nAdded) {
522            txBd->status = status | MCF5282_FEC_TxBD_R
523                                  | MCF5282_FEC_TxBD_L
524                                  | MCF5282_FEC_TxBD_TC;
525            if (nAdded > 1)
526                firstTxBd->status |= MCF5282_FEC_TxBD_R;
527            MCF5282_FEC_TDAR = MCF5282_FEC_TDAR_X_DES_ACTIVE;
528            sc->txBdActiveCount += nAdded;
529          }
530          break;
531        }
532        txBd->status = status;
533    }
534}
535
536void
537fec_txDaemon(void *arg)
538{
539    struct mcf5282_enet_struct *sc = (struct mcf5282_enet_struct *)arg;
540    struct ifnet *ifp = &sc->arpcom.ac_if;
541    struct mbuf *m;
542    rtems_event_set events;
543
544    for (;;) {
545        /*
546         * Wait for packet
547         */
548        rtems_bsdnet_event_receive(START_TRANSMIT_EVENT, 
549                                    RTEMS_EVENT_ANY | RTEMS_WAIT, 
550                                    RTEMS_NO_TIMEOUT, 
551                                    &events);
552
553        /*
554         * Send packets till queue is empty
555         */
556        for (;;) {
557            /*
558             * Get the next mbuf chain to transmit.
559             */
560            IF_DEQUEUE(&ifp->if_snd, m);
561            if (!m)
562                break;
563            fec_sendpacket(ifp, m);
564        }
565        ifp->if_flags &= ~IFF_OACTIVE;
566    }
567}
568
569
570/*
571 * Send packet (caller provides header).
572 */
573static void
574mcf5282_enet_start(struct ifnet *ifp)
575{
576    struct mcf5282_enet_struct *sc = ifp->if_softc;
577
578    rtems_event_send(sc->txDaemonTid, START_TRANSMIT_EVENT);
579    ifp->if_flags |= IFF_OACTIVE;
580}
581
582static void
583fec_init(void *arg)
584{
585    struct mcf5282_enet_struct *sc = arg;
586    struct ifnet *ifp = &sc->arpcom.ac_if;
587
588    if (sc->txDaemonTid == 0) {
589        /*
590         * Set up hardware
591         */
592        mcf5282_fec_initialize_hardware(sc);
593
594        /*
595         * Start driver tasks
596         */
597        sc->txDaemonTid = rtems_bsdnet_newproc("FECtx", 4096, fec_txDaemon, sc);
598        sc->rxDaemonTid = rtems_bsdnet_newproc("FECrx", 4096, fec_rxDaemon, sc);
599    }
600
601    /*
602     * Set flags appropriately
603     */
604    if (ifp->if_flags & IFF_PROMISC)
605        MCF5282_FEC_RCR |= MCF5282_FEC_RCR_PROM;
606    else
607        MCF5282_FEC_RCR &= ~MCF5282_FEC_RCR_PROM;
608
609    /*
610     * Tell the world that we're running.
611     */
612    ifp->if_flags |= IFF_RUNNING;
613
614    /*
615     * Enable receiver and transmitter
616     */
617    MCF5282_FEC_ECR = MCF5282_FEC_ECR_ETHER_EN;
618}
619
620
621static void
622fec_stop(struct mcf5282_enet_struct *sc)
623{
624    struct ifnet *ifp = &sc->arpcom.ac_if;
625
626    ifp->if_flags &= ~IFF_RUNNING;
627
628    /*
629     * Shut down receiver and transmitter
630     */
631    MCF5282_FEC_ECR = 0x0;
632}
633
634/*
635 * Show interface statistics
636 */
637static void
638enet_stats(struct mcf5282_enet_struct *sc)
639{
640    printf("  Rx Interrupts:%-10lu",   sc->rxInterrupts);
641    printf("Rx Packet Count:%-10lu",   MCF5282_FEC_RMON_R_PACKETS);
642    printf("   Rx Broadcast:%-10lu\n", MCF5282_FEC_RMON_R_BC_PKT);
643    printf("   Rx Multicast:%-10lu",   MCF5282_FEC_RMON_R_MC_PKT);
644    printf("CRC/Align error:%-10lu",   MCF5282_FEC_RMON_R_CRC_ALIGN);
645    printf("   Rx Undersize:%-10lu\n", MCF5282_FEC_RMON_R_UNDERSIZE);
646    printf("    Rx Oversize:%-10lu",   MCF5282_FEC_RMON_R_OVERSIZE);
647    printf("    Rx Fragment:%-10lu",   MCF5282_FEC_RMON_R_FRAG);
648    printf("      Rx Jabber:%-10lu\n", MCF5282_FEC_RMON_R_JAB);
649    printf("          Rx 64:%-10lu",   MCF5282_FEC_RMON_R_P64);
650    printf("      Rx 65-127:%-10lu",   MCF5282_FEC_RMON_R_P65T0127);
651    printf("     Rx 128-255:%-10lu\n", MCF5282_FEC_RMON_R_P128TO255);
652    printf("     Rx 256-511:%-10lu",   MCF5282_FEC_RMON_R_P256TO511);
653    printf("    Rx 511-1023:%-10lu",   MCF5282_FEC_RMON_R_P512TO1023);
654    printf("   Rx 1024-2047:%-10lu\n", MCF5282_FEC_RMON_R_P1024TO2047);
655    printf("      Rx >=2048:%-10lu",   MCF5282_FEC_RMON_R_GTE2048);
656    printf("      Rx Octets:%-10lu",   MCF5282_FEC_RMON_R_OCTETS);
657    printf("     Rx Dropped:%-10lu\n", MCF5282_FEC_IEEE_R_DROP);
658    printf("    Rx frame OK:%-10lu",   MCF5282_FEC_IEEE_R_FRAME_OK);
659    printf("   Rx CRC error:%-10lu",   MCF5282_FEC_IEEE_R_CRC);
660    printf(" Rx Align error:%-10lu\n", MCF5282_FEC_IEEE_R_ALIGN);
661    printf("  FIFO Overflow:%-10lu",   MCF5282_FEC_IEEE_R_MACERR);
662    printf("Rx Pause Frames:%-10lu",   MCF5282_FEC_IEEE_R_FDXFC);
663    printf("   Rx Octets OK:%-10lu\n", MCF5282_FEC_IEEE_R_OCTETS_OK);
664    printf("  Tx Interrupts:%-10lu",   sc->txInterrupts);
665    printf("Tx Output Waits:%-10lu",   sc->txRawWait);
666    printf("Tx Realignments:%-10lu\n",   sc->txRealign);
667    printf(" Tx Unaccounted:%-10lu", MCF5282_FEC_RMON_T_DROP);
668    printf("Tx Packet Count:%-10lu",   MCF5282_FEC_RMON_T_PACKETS);
669    printf("   Tx Broadcast:%-10lu\n",   MCF5282_FEC_RMON_T_BC_PKT);
670    printf("   Tx Multicast:%-10lu", MCF5282_FEC_RMON_T_MC_PKT);
671    printf("CRC/Align error:%-10lu",   MCF5282_FEC_RMON_T_CRC_ALIGN);
672    printf("   Tx Undersize:%-10lu\n",   MCF5282_FEC_RMON_T_UNDERSIZE);
673    printf("    Tx Oversize:%-10lu", MCF5282_FEC_RMON_T_OVERSIZE);
674    printf("    Tx Fragment:%-10lu",   MCF5282_FEC_RMON_T_FRAG);
675    printf("      Tx Jabber:%-10lu\n",   MCF5282_FEC_RMON_T_JAB);
676    printf("  Tx Collisions:%-10lu", MCF5282_FEC_RMON_T_COL);
677    printf("          Tx 64:%-10lu",   MCF5282_FEC_RMON_T_P64);
678    printf("      Tx 65-127:%-10lu\n",   MCF5282_FEC_RMON_T_P65TO127);
679    printf("     Tx 128-255:%-10lu", MCF5282_FEC_RMON_T_P128TO255);
680    printf("     Tx 256-511:%-10lu",   MCF5282_FEC_RMON_T_P256TO511);
681    printf("    Tx 511-1023:%-10lu\n",   MCF5282_FEC_RMON_T_P512TO1023);
682    printf("   Tx 1024-2047:%-10lu", MCF5282_FEC_RMON_T_P1024TO2047);
683    printf("      Tx >=2048:%-10lu",   MCF5282_FEC_RMON_T_P_GTE2048);
684    printf("      Tx Octets:%-10lu\n",   MCF5282_FEC_RMON_T_OCTETS);
685    printf("     Tx Dropped:%-10lu", MCF5282_FEC_IEEE_T_DROP);
686    printf("    Tx Frame OK:%-10lu",   MCF5282_FEC_IEEE_T_FRAME_OK);
687    printf(" Tx 1 Collision:%-10lu\n",   MCF5282_FEC_IEEE_T_1COL);
688    printf("Tx >1 Collision:%-10lu", MCF5282_FEC_IEEE_T_MCOL);
689    printf("    Tx Deferred:%-10lu",   MCF5282_FEC_IEEE_T_DEF);
690    printf(" Late Collision:%-10lu\n",   MCF5282_FEC_IEEE_T_LCOL);
691    printf(" Excessive Coll:%-10lu", MCF5282_FEC_IEEE_T_EXCOL);
692    printf("  FIFO Underrun:%-10lu",   MCF5282_FEC_IEEE_T_MACERR);
693    printf("  Carrier Error:%-10lu\n",   MCF5282_FEC_IEEE_T_CSERR);
694    printf("   Tx SQE Error:%-10lu", MCF5282_FEC_IEEE_T_SQE);
695    printf("Tx Pause Frames:%-10lu",   MCF5282_FEC_IEEE_T_FDXFC);
696    printf("   Tx Octets OK:%-10lu\n", MCF5282_FEC_IEEE_T_OCTETS_OK);
697}
698
699static int
700fec_ioctl(struct ifnet *ifp, int command, caddr_t data)
701{
702    struct mcf5282_enet_struct *sc = ifp->if_softc;
703    int error = 0;
704
705    switch (command) {
706        case SIOCGIFADDR:
707        case SIOCSIFADDR:
708            ether_ioctl(ifp, command, data);
709            break;
710
711        case SIOCSIFFLAGS:
712            switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
713                case IFF_RUNNING:
714                    fec_stop(sc);
715                    break;
716
717                case IFF_UP:
718                    fec_init(sc);
719                    break;
720
721                case IFF_UP | IFF_RUNNING:
722                    fec_stop(sc);
723                    fec_init(sc);
724                    break;
725
726                default:
727                    break;
728            }
729            break;
730
731        case SIO_RTEMS_SHOW_STATS:
732            enet_stats(sc);
733            break;
734
735            /*
736             * FIXME: All sorts of multicast commands need to be added here!
737             */
738        default:
739            error = EINVAL;
740            break;
741    }
742    return error;
743}
744
745int
746rtems_fec_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching )
747{
748    struct mcf5282_enet_struct *sc;
749    struct ifnet *ifp;
750    int mtu;
751    int unitNumber;
752    char *unitName;
753    unsigned char *hwaddr;
754
755    /*
756     * Parse driver name
757     */
758    if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0)
759        return 0;
760
761    /*
762     * Is driver free?
763     */
764    if ((unitNumber <= 0) || (unitNumber > NIFACES)) {
765        printf("Bad FEC unit number.\n");
766        return 0;
767    }
768    sc = &enet_driver[unitNumber - 1];
769    ifp = &sc->arpcom.ac_if;
770    if (ifp->if_softc != NULL) {
771        printf("Driver already in use.\n");
772        return 0;
773    }
774
775    /*
776     * Process options
777     */
778    if (config->hardware_address) {
779        hwaddr = config->hardware_address;
780    }
781    else if ((hwaddr = uC5282_gethwaddr(unitNumber - 1)) == NULL) {
782        /* Locally-administered address */
783        static const char defaultAddress[ETHER_ADDR_LEN] = {
784                                            0x06, 'R', 'T', 'E', 'M', 'S'};
785        printf ("WARNING -- No %s%d Ethernet address specified -- Using default address.\n",
786                                                        unitName, unitNumber);
787        hwaddr = defaultAddress;
788    }
789    printf("%s%d: Ethernet address: %02x:%02x:%02x:%02x:%02x:%02x\n",
790                                            unitName, unitNumber,
791                                            hwaddr[0], hwaddr[1], hwaddr[2],
792                                            hwaddr[3], hwaddr[4], hwaddr[5]);
793    memcpy(sc->arpcom.ac_enaddr, hwaddr, ETHER_ADDR_LEN);
794
795    if (config->mtu)
796        mtu = config->mtu;
797    else
798        mtu = ETHERMTU;
799    if (config->rbuf_count)
800        sc->rxBdCount = config->rbuf_count;
801    else
802        sc->rxBdCount = RX_BUF_COUNT;
803    if (config->xbuf_count)
804        sc->txBdCount = config->xbuf_count;
805    else
806        sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF;
807
808    sc->acceptBroadcast = !config->ignore_broadcast;
809
810    /*
811     * Set up network interface values
812     */
813    ifp->if_softc = sc;
814    ifp->if_unit = unitNumber;
815    ifp->if_name = unitName;
816    ifp->if_mtu = mtu;
817    ifp->if_init = fec_init;
818    ifp->if_ioctl = fec_ioctl;
819    ifp->if_start = mcf5282_enet_start;
820    ifp->if_output = ether_output;
821    ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
822    if (ifp->if_snd.ifq_maxlen == 0)
823        ifp->if_snd.ifq_maxlen = ifqmaxlen;
824
825    /*
826     * Attach the interface
827     */
828    if_attach(ifp);
829    ether_ifattach(ifp);
830    return 1;
831};
832
Note: See TracBrowser for help on using the repository browser.