source: rtems/bsps/m68k/csb360/net/network.c @ 68920e7f

Last change on this file since 68920e7f was cb68253, checked in by Sebastian Huber <sebastian.huber@…>, on Sep 7, 2018 at 4:19:02 AM

network: Use kernel/user space header files

Add and use <machine/rtems-bsd-kernel-space.h> and
<machine/rtems-bsd-user-space.h> similar to the libbsd to avoid command
line defines and defines scattered throught the code base.

Simplify cpukit/libnetworking/Makefile.am.

Update #3375.

  • Property mode set to 100644
File size: 26.8 KB
Line 
1/*
2 * RTEMS/TCPIP driver for MCF5272 Ethernet
3 *
4 *  Modified for MPC860 by Jay Monkman (jmonkman@lopingdog.com)
5 *
6 *  This supports Ethernet on either SCC1 or the FEC of the MPC860T.
7 *  Right now, we only do 10 Mbps, even with the FEC. The function
8 *  rtems_enet_driver_attach determines which one to use. Currently,
9 *  only one may be used at a time.
10 *
11 *  Based on the MC68360 network driver by
12 *  W. Eric Norum
13 *  Saskatchewan Accelerator Laboratory
14 *  University of Saskatchewan
15 *  Saskatoon, Saskatchewan, CANADA
16 *  eric@skatter.usask.ca
17 *
18 *  This supports ethernet on SCC1. Right now, we only do 10 Mbps.
19 *
20 *  Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca>
21 *  and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca>
22 *  Copyright (c) 1999, National Research Council of Canada
23 */
24
25#include <machine/rtems-bsd-kernel-space.h>
26
27#include <bsp.h>
28#include <stdio.h>
29#include <rtems/error.h>
30#include <rtems/rtems_bsdnet.h>
31
32#include <sys/param.h>
33#include <sys/mbuf.h>
34#include <sys/socket.h>
35#include <sys/sockio.h>
36
37#include <net/if.h>
38
39#include <netinet/in.h>
40#include <netinet/if_ether.h>
41
42#include <sys/types.h>
43#include <sys/socket.h>
44
45/*
46 * Number of interfaces supported by this driver
47 */
48#define NIFACES 1
49
50/*
51 * Default number of buffer descriptors set aside for this driver.
52 * The number of transmit buffer descriptors has to be quite large
53 * since a single frame often uses four or more buffer descriptors.
54 */
55#define RX_BUF_COUNT     32
56#define TX_BUF_COUNT     16
57#define TX_BD_PER_BUF    4
58
59#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255")
60
61
62/*
63 * RTEMS event used by interrupt handler to signal daemons.
64 * This must *not* be the same event used by the TCP/IP task synchronization.
65 */
66#define INTERRUPT_EVENT RTEMS_EVENT_1
67
68/*
69 * RTEMS event used to start transmit daemon.
70 * This must not be the same as INTERRUPT_EVENT.
71 */
72#define START_TRANSMIT_EVENT RTEMS_EVENT_2
73
74/*
75 * Receive buffer size -- Allow for a full ethernet packet plus CRC (1518).
76 * Round off to nearest multiple of RBUF_ALIGN.
77 */
78#define MAX_MTU_SIZE    1518
79#define RBUF_ALIGN              4
80#define RBUF_SIZE       ((MAX_MTU_SIZE + RBUF_ALIGN) & ~RBUF_ALIGN)
81
82#if (MCLBYTES < RBUF_SIZE)
83# error "Driver must have MCLBYTES > RBUF_SIZE"
84#endif
85
86typedef struct {
87    uint16_t status;
88    uint16_t length;
89    void *buffer;
90} bd_t;
91#define MCF5272_BD_READY       (bit(15))
92#define MCF5272_BD_TO1         (bit(14))
93#define MCF5272_BD_WRAP        (bit(13))
94#define MCF5272_BD_TO2         (bit(12))
95#define MCF5272_BD_LAST        (bit(11))
96#define MCF5272_BD_TX_CRC          (bit(10))
97#define MCF5272_BD_DEFER       (bit(9))
98#define MCF5272_BD_HEARTBEAT   (bit(8))
99#define MCF5272_BD_LATE_COLLISION       (bit(7))
100#define MCF5272_BD_RETRY_LIMIT          (bit(6))
101#define MCF5272_BD_UNDERRUN          (bit(1))
102#define MCF5272_BD_CARRIER_LOST         (bit(0))
103
104#define MCF5272_BD_EMPTY           (bit(15))
105#define MCF5272_BD_RO1         (bit(14))
106#define MCF5272_BD_WRAP        (bit(13))
107#define MCF5272_BD_RO2         (bit(12))
108#define MCF5272_BD_M           (bit(8))
109#define MCF5272_BD_BC          (bit(7))
110#define MCF5272_BD_MC          (bit(6))
111#define MCF5272_BD_LONG          (bit(5))
112#define MCF5272_BD_NONALIGNED          (bit(4))
113#define MCF5272_BD_SHORT          (bit(3))
114#define MCF5272_BD_CRC_ERROR          (bit(2))
115#define MCF5272_BD_OVERRUN          (bit(1))
116#define MCF5272_BD_TRUNCATED          (bit(0))
117
118
119/*
120 * Per-device data
121 */
122struct mcf5272_enet_struct {
123    struct arpcom           arpcom;
124    struct mbuf             **rxMbuf;
125    struct mbuf             **txMbuf;
126    int                     acceptBroadcast;
127    int                     rxBdCount;
128    int                     txBdCount;
129    int                     txBdHead;
130    int                     txBdTail;
131    int                     txBdActiveCount;
132    bd_t                   *rxBdBase;
133    bd_t                   *txBdBase;
134    rtems_id                rxDaemonTid;
135    rtems_id                txDaemonTid;
136
137    /*
138     * Statistics
139     */
140    unsigned long   rxInterrupts;
141    unsigned long   rxNotFirst;
142    unsigned long   rxNotLast;
143    unsigned long   rxGiant;
144    unsigned long   rxNonOctet;
145    unsigned long   rxRunt;
146    unsigned long   rxBadCRC;
147    unsigned long   rxOverrun;
148    unsigned long   rxTruncated;
149
150    unsigned long   txInterrupts;
151    unsigned long   txDeferred;
152    unsigned long   txHeartbeat;
153    unsigned long   txLateCollision;
154    unsigned long   txRetryLimit;
155    unsigned long   txUnderrun;
156    unsigned long   txLostCarrier;
157    unsigned long   txRawWait;
158};
159static struct mcf5272_enet_struct enet_driver[NIFACES];
160
161
162void dump_enet_regs(void)
163{
164    printf("**************************************************************\n");
165   printf("ecr:   0x%08x  eir:   0x%08x  eimr:  0x%08x  ivsr:  0x%08x\n\r",
166          g_enet_regs->ecr, g_enet_regs->eir,
167          g_enet_regs->eimr, g_enet_regs->ivsr);
168   printf("rdar:  0x%08x  tdar:  0x%08x  mmfr:  0x%08x  mscr:  0x%08x\n\r",
169          g_enet_regs->rdar, g_enet_regs->tdar,
170          g_enet_regs->mmfr, g_enet_regs->mscr);
171   printf("frbr:  0x%08x  frsr:  0x%08x  tfwr:  0x%08x  tfsr:  0x%08x\n\r",
172          g_enet_regs->frbr, g_enet_regs->frsr,
173          g_enet_regs->tfwr, g_enet_regs->tfsr);
174   printf("rcr:   0x%08x  mflr:  0x%08x  tcr:   0x%08x  malr:  0x%08x\n\r",
175          g_enet_regs->rcr, g_enet_regs->mflr,
176          g_enet_regs->tcr, g_enet_regs->malr);
177   printf("maur:  0x%08x  htur:  0x%08x  htlr:  0x%08x  erdsr: 0x%08x\n\r",
178          g_enet_regs->maur, g_enet_regs->htur,
179          g_enet_regs->htlr, g_enet_regs->erdsr);
180   printf("etdsr: 0x%08x  emrbr: 0x%08x\n\r",
181          g_enet_regs->etdsr, g_enet_regs->emrbr);
182}
183
184
185
186
187/*#define cp printk("%s:%d\n\r", __FUNCTION__, __LINE__) */
188#define cp
189#define mcf5272_bd_allocate(_n_) malloc((_n_) * sizeof(bd_t), 0, M_NOWAIT)
190
191
192
193rtems_isr enet_rx_isr(rtems_vector_number vector)
194{
195    cp;
196    /*
197     * Frame received?
198     */
199    if (g_enet_regs->eir & MCF5272_ENET_EIR_RXF) {
200        cp;
201        g_enet_regs->eir = MCF5272_ENET_EIR_RXF;
202        enet_driver[0].rxInterrupts++;
203        rtems_bsdnet_event_send (enet_driver[0].rxDaemonTid, INTERRUPT_EVENT);
204    }
205    cp;
206}
207
208rtems_isr enet_tx_isr(rtems_vector_number vector)
209{
210    cp;
211    /*
212     * Buffer transmitted or transmitter error?
213     */
214    if (g_enet_regs->eir & MCF5272_ENET_EIR_TXF) {
215        cp;
216        g_enet_regs->eir = MCF5272_ENET_EIR_TXF;
217        enet_driver[0].txInterrupts++;
218        rtems_bsdnet_event_send (enet_driver[0].txDaemonTid, INTERRUPT_EVENT);
219    }
220    cp;
221}
222
223
224/*
225 * Initialize the ethernet hardware
226 */
227
228
229static void
230mcf5272_enet_initialize_hardware (struct mcf5272_enet_struct *sc)
231{
232    int i;
233    unsigned char *hwaddr;
234    uint32_t icr;
235    /*
236     * Issue reset to FEC
237     */
238    g_enet_regs->ecr=0x1;
239
240    /*
241     * Set the TX and RX fifo sizes. For now, we'll split it evenly
242     */
243    /* If you uncomment these, the FEC will not work right.
244       g_enet_regs->r_fstart = ((g_enet_regs->r_bound & 0x3ff) >> 2) & 0x3ff;
245       g_enet_regs->x_fstart = 0;
246    */
247
248    /* Copy mac address to device */
249
250    hwaddr = sc->arpcom.ac_enaddr;
251
252    g_enet_regs->malr = (hwaddr[0] << 24 |
253                         hwaddr[1] << 16 |
254                         hwaddr[2] << 8 |
255                         hwaddr[3]);
256    g_enet_regs->maur = (hwaddr[4] << 24 |
257                         hwaddr[5] << 16);
258
259    /*
260     * Clear the hash table
261     */
262    g_enet_regs->htlr = 0;
263    g_enet_regs->htur  = 0;
264
265    /*
266     * Set up receive buffer size
267     */
268    g_enet_regs->emrbr = 0x5f0; /* set to 1520 */
269
270    /*
271     * Allocate mbuf pointers
272     */
273    sc->rxMbuf = malloc (sc->rxBdCount * sizeof *sc->rxMbuf,
274                         M_MBUF, M_NOWAIT);
275    sc->txMbuf = malloc (sc->txBdCount * sizeof *sc->txMbuf,
276                         M_MBUF, M_NOWAIT);
277    if (!sc->rxMbuf || !sc->txMbuf) {
278        rtems_panic ("No memory for mbuf pointers");
279    }
280
281    /*
282     * Set receiver and transmitter buffer descriptor bases
283     */
284    sc->rxBdBase = mcf5272_bd_allocate(sc->rxBdCount);
285    sc->txBdBase = mcf5272_bd_allocate(sc->txBdCount);
286    g_enet_regs->erdsr = (int)sc->rxBdBase;
287    g_enet_regs->etdsr = (int)sc->txBdBase;
288
289    /*
290     * Set up Receive Control Register:
291     *   Not promiscuous mode
292     *   MII mode
293     *   Full duplex
294     *   No loopback
295     */
296    g_enet_regs->rcr = 0x00000004;
297
298    /*
299     * Set up Transmit Control Register:
300     *   Full duplex
301     *   No heartbeat
302     */
303    g_enet_regs->tcr = 0x00000004;
304
305    /*
306     * Set MII speed to 2.5 MHz for 25 Mhz system clock
307     */
308    g_enet_regs->mscr = 0x0a;
309    g_enet_regs->mmfr = 0x58021000;
310
311    /*
312     * Set up receive buffer descriptors
313     */
314    for (i = 0 ; i < sc->rxBdCount ; i++) {
315        (sc->rxBdBase + i)->status = 0;
316    }
317
318    /*
319     * Set up transmit buffer descriptors
320     */
321    for (i = 0 ; i < sc->txBdCount ; i++) {
322        (sc->txBdBase + i)->status = 0;
323        sc->txMbuf[i] = NULL;
324    }
325
326    sc->txBdHead = sc->txBdTail = 0;
327    sc->txBdActiveCount = 0;
328
329    /*
330     * Mask all FEC interrupts and clear events
331     */
332    g_enet_regs->eimr = (MCF5272_ENET_EIR_TXF |
333                        MCF5272_ENET_EIR_RXF);
334    g_enet_regs->eir = ~0;
335
336    /*
337     * Set up interrupts
338     */
339    set_vector(enet_rx_isr, BSP_INTVEC_ERX, 1);
340    set_vector(enet_tx_isr, BSP_INTVEC_ETX, 1);
341
342    /* Configure ethernet interrupts */
343    icr = g_intctrl_regs->icr3;
344    icr = icr & ~((MCF5272_ICR3_ERX_MASK | MCF5272_ICR3_ERX_PI) |
345                  (MCF5272_ICR3_ETX_MASK | MCF5272_ICR3_ETX_PI));
346    icr |= ((MCF5272_ICR3_ERX_IPL(BSP_INTLVL_ERX) | MCF5272_ICR3_ERX_PI)|
347            (MCF5272_ICR3_ETX_IPL(BSP_INTLVL_ETX) | MCF5272_ICR3_ETX_PI));
348    g_intctrl_regs->icr3 = icr;
349
350}
351
352
353/*
354 * Soak up buffer descriptors that have been sent.
355 * Note that a buffer descriptor can't be retired as soon as it becomes
356 * ready. The MPC860 manual (MPC860UM/AD 07/98 Rev.1) and the MPC821
357 * manual state that, "If an Ethernet frame is made up of multiple
358 * buffers, the user should not reuse the first buffer descriptor until
359 * the last buffer descriptor of the frame has had its ready bit cleared
360 * by the CPM".
361 */
362static void
363mcf5272_enet_retire_tx_bd (struct mcf5272_enet_struct *sc)
364{
365    uint16_t status;
366    int i;
367    int nRetired;
368    struct mbuf *m, *n;
369
370    i = sc->txBdTail;
371    nRetired = 0;
372    while ((sc->txBdActiveCount != 0) &&
373           (((status = sc->txBdBase[i].status) & MCF5272_BD_READY) == 0)) {
374        /*
375         * See if anything went wrong
376         */
377        if (status & (MCF5272_BD_DEFER |
378                      MCF5272_BD_HEARTBEAT |
379                      MCF5272_BD_LATE_COLLISION |
380                      MCF5272_BD_RETRY_LIMIT |
381                      MCF5272_BD_UNDERRUN |
382                      MCF5272_BD_CARRIER_LOST)) {
383            /*
384             * Check for errors which stop the transmitter.
385             */
386            if (status & (MCF5272_BD_LATE_COLLISION |
387                          MCF5272_BD_RETRY_LIMIT |
388                          MCF5272_BD_UNDERRUN)) {
389                if (status & MCF5272_BD_LATE_COLLISION) {
390                    enet_driver[0].txLateCollision++;
391                }
392                if (status & MCF5272_BD_RETRY_LIMIT) {
393                    enet_driver[0].txRetryLimit++;
394                }
395                if (status & MCF5272_BD_UNDERRUN) {
396                    enet_driver[0].txUnderrun++;
397                }
398            }
399            if (status & MCF5272_BD_DEFER) {
400                enet_driver[0].txDeferred++;
401            }
402            if (status & MCF5272_BD_HEARTBEAT) {
403                enet_driver[0].txHeartbeat++;
404            }
405            if (status & MCF5272_BD_CARRIER_LOST) {
406                enet_driver[0].txLostCarrier++;
407            }
408        }
409        nRetired++;
410        if (status & MCF5272_BD_LAST) {
411            /*
412             * A full frame has been transmitted.
413             * Free all the associated buffer descriptors.
414             */
415            sc->txBdActiveCount -= nRetired;
416            while (nRetired) {
417                nRetired--;
418                m = sc->txMbuf[sc->txBdTail];
419                MFREE (m, n);
420                if (++sc->txBdTail == sc->txBdCount)
421                    sc->txBdTail = 0;
422            }
423        }
424        if (++i == sc->txBdCount) {
425            i = 0;
426        }
427    }
428}
429
430static void
431mcf5272_enet_rxDaemon (void *arg)
432{
433    struct mcf5272_enet_struct *sc = (struct mcf5272_enet_struct *)arg;
434    struct ifnet *ifp = &sc->arpcom.ac_if;
435    struct mbuf *m;
436    uint16_t status;
437    bd_t *rxBd;
438    int rxBdIndex;
439
440    /*
441     * Allocate space for incoming packets and start reception
442     */
443    for (rxBdIndex = 0 ; ;) {
444        rxBd = sc->rxBdBase + rxBdIndex;
445        MGETHDR (m, M_WAIT, MT_DATA);
446        MCLGET (m, M_WAIT);
447        m->m_pkthdr.rcvif = ifp;
448        sc->rxMbuf[rxBdIndex] = m;
449        rxBd->buffer = mtod (m, void *);
450        rxBd->status = MCF5272_BD_EMPTY;
451        g_enet_regs->rdar = 0x1000000;
452        if (++rxBdIndex == sc->rxBdCount) {
453            rxBd->status |= MCF5272_BD_WRAP;
454            break;
455        }
456    }
457
458    /*
459     * Input packet handling loop
460     */
461    rxBdIndex = 0;
462    for (;;) {
463        rxBd = sc->rxBdBase + rxBdIndex;
464
465        /*
466         * Wait for packet if there's not one ready
467         */
468        if ((status = rxBd->status) & MCF5272_BD_EMPTY) {
469            /*
470             * Clear old events
471             */
472            g_enet_regs->eir = MCF5272_ENET_EIR_RXF;
473
474            /*
475             * Wait for packet
476             * Note that the buffer descriptor is checked
477             * *before* the event wait -- this catches the
478             * possibility that a packet arrived between the
479             * `if' above, and the clearing of the event register.
480             */
481            while ((status = rxBd->status) & MCF5272_BD_EMPTY) {
482                rtems_event_set events;
483
484                /*
485                 * Unmask RXF (Full frame received) event
486                 */
487                g_enet_regs->eir |= MCF5272_ENET_EIR_RXF;
488
489                rtems_bsdnet_event_receive (INTERRUPT_EVENT,
490                                            RTEMS_WAIT|RTEMS_EVENT_ANY,
491                                            RTEMS_NO_TIMEOUT,
492                                            &events);
493                cp;
494            }
495        }
496    cp;
497
498        /*
499         * Check that packet is valid
500         */
501        if (status & MCF5272_BD_LAST) {
502            /*
503             * Pass the packet up the chain.
504             * FIXME: Packet filtering hook could be done here.
505             */
506            struct ether_header *eh;
507
508            m = sc->rxMbuf[rxBdIndex];
509            m->m_len = m->m_pkthdr.len = (rxBd->length -
510                                          sizeof(uint32_t) -
511                                          sizeof(struct ether_header));
512            eh = mtod (m, struct ether_header *);
513            m->m_data += sizeof(struct ether_header);
514            ether_input (ifp, eh, m);
515
516            /*
517             * Allocate a new mbuf
518             */
519            MGETHDR (m, M_WAIT, MT_DATA);
520            MCLGET (m, M_WAIT);
521            m->m_pkthdr.rcvif = ifp;
522            sc->rxMbuf[rxBdIndex] = m;
523            rxBd->buffer = mtod (m, void *);
524        }
525        else {
526            /*
527             * Something went wrong with the reception
528             */
529            if (!(status & MCF5272_BD_LAST)) {
530                sc->rxNotLast++;
531            }
532            if (status & MCF5272_BD_LONG) {
533                sc->rxGiant++;
534            }
535            if (status & MCF5272_BD_NONALIGNED) {
536                sc->rxNonOctet++;
537            }
538            if (status & MCF5272_BD_SHORT) {
539                sc->rxRunt++;
540            }
541            if (status & MCF5272_BD_CRC_ERROR) {
542                sc->rxBadCRC++;
543            }
544            if (status & MCF5272_BD_OVERRUN) {
545                sc->rxOverrun++;
546            }
547            if (status & MCF5272_BD_TRUNCATED) {
548                sc->rxTruncated++;
549            }
550        }
551        /*
552         * Reenable the buffer descriptor
553         */
554        rxBd->status = (status & MCF5272_BD_WRAP) | MCF5272_BD_EMPTY;
555        g_enet_regs->rdar = 0x1000000;
556        /*
557         * Move to next buffer descriptor
558         */
559        if (++rxBdIndex == sc->rxBdCount) {
560            rxBdIndex = 0;
561        }
562    }
563}
564
565static void
566mcf5272_enet_sendpacket (struct ifnet *ifp, struct mbuf *m)
567{
568    struct mcf5272_enet_struct *sc = ifp->if_softc;
569    volatile bd_t *firstTxBd, *txBd;
570    /*  struct mbuf *l = NULL; */
571    uint16_t status;
572    int nAdded;
573    cp;
574
575    /*
576     * Free up buffer descriptors
577     */
578    mcf5272_enet_retire_tx_bd (sc);
579
580    /*
581     * Set up the transmit buffer descriptors.
582     * No need to pad out short packets since the
583     * hardware takes care of that automatically.
584     * No need to copy the packet to a contiguous buffer
585     * since the hardware is capable of scatter/gather DMA.
586     */
587    nAdded = 0;
588    txBd = firstTxBd = sc->txBdBase + sc->txBdHead;
589    for (;;) {
590    cp;
591        /*
592         * Wait for buffer descriptor to become available.
593         */
594        if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
595            /*
596             * Clear old events
597             */
598            g_enet_regs->eir = MCF5272_ENET_EIR_TXF;
599
600            /*
601             * Wait for buffer descriptor to become available.
602             * Note that the buffer descriptors are checked
603             * *before* * entering the wait loop -- this catches
604             * the possibility that a buffer descriptor became
605             * available between the `if' above, and the clearing
606             * of the event register.
607             * This is to catch the case where the transmitter
608             * stops in the middle of a frame -- and only the
609             * last buffer descriptor in a frame can generate
610             * an interrupt.
611             */
612            mcf5272_enet_retire_tx_bd (sc);
613            while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
614                rtems_event_set events;
615
616                cp;
617                /*
618                 * Unmask TXB (buffer transmitted) and
619                 * TXE (transmitter error) events.
620                 */
621                g_enet_regs->eir |= MCF5272_ENET_EIR_TXF;
622                rtems_bsdnet_event_receive (INTERRUPT_EVENT,
623                                            RTEMS_WAIT|RTEMS_EVENT_ANY,
624                                            RTEMS_NO_TIMEOUT,
625                                            &events);
626                cp;
627                mcf5272_enet_retire_tx_bd (sc);
628            }
629        }
630
631        /*
632         * Don't set the READY flag till the
633         * whole packet has been readied.
634         */
635        status = nAdded ? MCF5272_BD_READY : 0;
636        cp;
637
638        /*
639         *  FIXME: Why not deal with empty mbufs at at higher level?
640         * The IP fragmentation routine in ip_output
641         * can produce packet fragments with zero length.
642         * I think that ip_output should be changed to get
643         * rid of these zero-length mbufs, but for now,
644         * I'll deal with them here.
645         */
646        if (m->m_len) {
647            cp;
648            /*
649             * Fill in the buffer descriptor
650             */
651            txBd->buffer = mtod (m, void *);
652            txBd->length = m->m_len;
653
654            sc->txMbuf[sc->txBdHead] = m;
655            nAdded++;
656            if (++sc->txBdHead == sc->txBdCount) {
657                status |= MCF5272_BD_WRAP;
658                sc->txBdHead = 0;
659            }
660            /*      l = m;*/
661            m = m->m_next;
662        }
663        else {
664            /*
665             * Just toss empty mbufs
666             */
667            struct mbuf *n;
668            cp;
669            MFREE (m, n);
670            m = n;
671            /*
672              if (l != NULL)
673              l->m_next = m;
674            */
675        }
676
677        /*
678         * Set the transmit buffer status.
679         * Break out of the loop if this mbuf is the last in the frame.
680         */
681        if (m == NULL) {
682            cp;
683            if (nAdded) {
684                cp;
685                status |= MCF5272_BD_LAST | MCF5272_BD_TX_CRC;
686                txBd->status = status;
687                firstTxBd->status |= MCF5272_BD_READY;
688                g_enet_regs->tdar = 0x1000000;
689                sc->txBdActiveCount += nAdded;
690            }
691            break;
692        }
693        txBd->status = status;
694        txBd = sc->txBdBase + sc->txBdHead;
695    }
696    cp;
697/*
698    dump_enet_regs();
699    dump_intctrl;
700*/
701
702}
703
704
705void
706mcf5272_enet_txDaemon (void *arg)
707{
708    struct mcf5272_enet_struct *sc = (struct mcf5272_enet_struct *)arg;
709    struct ifnet *ifp = &sc->arpcom.ac_if;
710    struct mbuf *m;
711    rtems_event_set events;
712
713    cp;
714    for (;;) {
715        /*
716         * Wait for packet
717         */
718        rtems_bsdnet_event_receive (START_TRANSMIT_EVENT,
719                                    RTEMS_EVENT_ANY | RTEMS_WAIT,
720                                    RTEMS_NO_TIMEOUT,
721                                    &events);
722        cp;
723        /*
724         * Send packets till queue is empty
725         */
726    cp;
727        for (;;) {
728    cp;
729            /*
730             * Get the next mbuf chain to transmit.
731             */
732            IF_DEQUEUE(&ifp->if_snd, m);
733            if (!m)
734                break;
735            mcf5272_enet_sendpacket (ifp, m);
736        }
737        ifp->if_flags &= ~IFF_OACTIVE;
738    }
739}
740
741
742/*
743 * Send packet (caller provides header).
744 */
745static void
746mcf5272_enet_start (struct ifnet *ifp)
747{
748    struct mcf5272_enet_struct *sc = ifp->if_softc;
749
750    cp;
751    rtems_bsdnet_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
752    cp;
753    ifp->if_flags |= IFF_OACTIVE;
754}
755
756
757static void
758mcf5272_enet_init (void *arg)
759{
760    struct mcf5272_enet_struct *sc = arg;
761    struct ifnet *ifp = &sc->arpcom.ac_if;
762
763    if (sc->txDaemonTid == 0) {
764
765        /*
766         * Set up SCC hardware
767         */
768        mcf5272_enet_initialize_hardware (sc);
769
770        /*
771         * Start driver tasks
772         */
773        sc->txDaemonTid = rtems_bsdnet_newproc("SCtx",
774                                               4096,
775                                               mcf5272_enet_txDaemon,
776                                               sc);
777        sc->rxDaemonTid = rtems_bsdnet_newproc("SCrx",
778                                               4096,
779                                               mcf5272_enet_rxDaemon,
780                                               sc);
781
782    }
783
784    /*
785     * Set flags appropriately
786     */
787    if (ifp->if_flags & IFF_PROMISC) {
788        g_enet_regs->rcr |= 0x8;
789    } else {
790        g_enet_regs->rcr &= ~0x8;
791    }
792
793    /*
794     * Tell the world that we're running.
795     */
796    ifp->if_flags |= IFF_RUNNING;
797
798    /*
799     * Enable receiver and transmitter
800     */
801    g_enet_regs->ecr = 0x2;
802}
803
804
805static void
806mcf5272_enet_stop (struct mcf5272_enet_struct *sc)
807{
808    struct ifnet *ifp = &sc->arpcom.ac_if;
809
810    ifp->if_flags &= ~IFF_RUNNING;
811
812    /*
813     * Shut down receiver and transmitter
814     */
815    g_enet_regs->ecr = 0x0;
816}
817
818
819/*
820 * Show interface statistics
821 */
822static void
823enet_stats (struct mcf5272_enet_struct *sc)
824{
825    printf ("      Rx Interrupts:%-8lu", sc->rxInterrupts);
826    printf ("       Not First:%-8lu", sc->rxNotFirst);
827    printf ("        Not Last:%-8lu\n", sc->rxNotLast);
828    printf ("              Giant:%-8lu", sc->rxGiant);
829    printf ("            Runt:%-8lu", sc->rxRunt);
830    printf ("       Non-octet:%-8lu\n", sc->rxNonOctet);
831    printf ("            Bad CRC:%-8lu", sc->rxBadCRC);
832    printf ("         Overrun:%-8lu", sc->rxOverrun);
833    printf ("       Truncated:%-8lu\n", sc->rxTruncated);
834/*    printf ("          Discarded:%-8lu\n", (unsigned long)mcf5272.scc1p.un.ethernet.disfc); */
835
836    printf ("      Tx Interrupts:%-8lu", sc->txInterrupts);
837    printf ("        Deferred:%-8lu", sc->txDeferred);
838    printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat);
839    printf ("         No Carrier:%-8lu", sc->txLostCarrier);
840    printf ("Retransmit Limit:%-8lu", sc->txRetryLimit);
841    printf ("  Late Collision:%-8lu\n", sc->txLateCollision);
842    printf ("           Underrun:%-8lu", sc->txUnderrun);
843    printf (" Raw output wait:%-8lu\n", sc->txRawWait);
844}
845
846
847/*
848 * Driver ioctl handler
849 */
850static int
851mcf5272_enet_ioctl (struct ifnet *ifp, int command, caddr_t data)
852{
853    struct mcf5272_enet_struct *sc = ifp->if_softc;
854    int error = 0;
855
856    switch (command) {
857    case SIOCGIFADDR:
858    case SIOCSIFADDR:
859        ether_ioctl (ifp, command, data);
860        break;
861
862    case SIOCSIFFLAGS:
863        switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
864        case IFF_RUNNING:
865            mcf5272_enet_stop (sc);
866            break;
867
868        case IFF_UP:
869            mcf5272_enet_init (sc);
870            break;
871
872        case IFF_UP | IFF_RUNNING:
873            mcf5272_enet_stop (sc);
874            mcf5272_enet_init (sc);
875            break;
876
877        default:
878            break;
879        }
880        break;
881
882    case SIO_RTEMS_SHOW_STATS:
883        enet_stats (sc);
884        break;
885
886        /*
887         * FIXME: All sorts of multicast commands need to be added here!
888         */
889    default:
890        error = EINVAL;
891        break;
892    }
893    return error;
894}
895
896
897int
898rtems_enet_driver_attach (struct rtems_bsdnet_ifconfig *config)
899{
900    struct mcf5272_enet_struct *sc;
901    struct ifnet *ifp;
902    int mtu;
903    int unitNumber;
904    char *unitName;
905
906    /*
907     * Parse driver name
908     */
909    unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName);
910    if (unitNumber < 0){
911        return 0;
912    }
913
914    /*
915     * Is driver free?
916     */
917    if ((unitNumber < 0) || (unitNumber > NIFACES)) {
918        printf ("Bad unit number: %d.\n", unitNumber);
919        return 0;
920    }
921
922    sc = &enet_driver[unitNumber];
923    ifp = &sc->arpcom.ac_if;
924    if (ifp->if_softc != NULL) {
925        printf ("Driver already in use.\n");
926        return 0;
927    }
928
929    /*
930     * Process options
931     */
932
933    sc->arpcom.ac_enaddr[0] = (g_enet_regs->malr >> 24) & 0xff;
934    sc->arpcom.ac_enaddr[1] = (g_enet_regs->malr >> 16) & 0xff;
935    sc->arpcom.ac_enaddr[2] = (g_enet_regs->malr >> 8) & 0xff;
936    sc->arpcom.ac_enaddr[3] = (g_enet_regs->malr >> 0) & 0xff;
937    sc->arpcom.ac_enaddr[4] = (g_enet_regs->maur >> 24) & 0xff;
938    sc->arpcom.ac_enaddr[5] = (g_enet_regs->maur >> 16) & 0xff;
939
940    if (config->mtu) {
941        mtu = config->mtu;
942    } else {
943        mtu = ETHERMTU;
944    }
945
946    if (config->rbuf_count) {
947        sc->rxBdCount = config->rbuf_count;
948    } else {
949        sc->rxBdCount = RX_BUF_COUNT;
950    }
951    if (config->xbuf_count) {
952        sc->txBdCount = config->xbuf_count;
953    } else {
954        sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF;
955    }
956    sc->acceptBroadcast = !config->ignore_broadcast;
957
958    /*
959     * Set up network interface values
960     */
961    ifp->if_softc = sc;
962    ifp->if_unit = unitNumber;
963    ifp->if_name = unitName;
964    ifp->if_mtu = mtu;
965    ifp->if_init = mcf5272_enet_init;
966    ifp->if_ioctl = mcf5272_enet_ioctl;
967    ifp->if_start = mcf5272_enet_start;
968    ifp->if_output = ether_output;
969    ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
970    if (ifp->if_snd.ifq_maxlen == 0) {
971        ifp->if_snd.ifq_maxlen = ifqmaxlen;
972    }
973
974    /*
975     * Attach the interface
976     */
977    if_attach (ifp);
978    cp;
979    ether_ifattach (ifp);
980    cp;
981    return 1;
982};
983
984
Note: See TracBrowser for help on using the repository browser.