source: rtems/c/src/lib/libbsp/m68k/csb360/network/network.c @ 4c02385

5
Last change on this file since 4c02385 was 4c02385, checked in by Christian Mauderer <Christian.Mauderer@…>, on 06/24/16 at 06:52:48

libnetworking: Import current <arpa/inet.h>

Import the <arpa/inet.h> from current FreeBSD. Necessary due to changes
in <netinet/in.h>. Remove BSD hack from <arpa/inet.h>.

Clean up problems with htonl(). These functions are defined in
<arpa/inet.h>. This lead to some problems because they are defined in
<rtems/endian.h> too. Add NTOHL, ... to
<rtems/rtems_bsdnet_internal.h>.

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