source: rtems/bsps/mips/csb350/net/network.c @ cb68253

5
Last change on this file since cb68253 was cb68253, checked in by Sebastian Huber <sebastian.huber@…>, on 09/07/18 at 04:19:02

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: 25.7 KB
Line 
1/**
2 *  @file
3 * 
4 *  Au1x00 ethernet driver
5 */
6
7/*
8 *  Copyright (c) 2005 by Cogent Computer Systems
9 *  Written by Jay Monkman <jtm@lopingdog.com>
10 *
11 *  The license and distribution terms for this file may be
12 *  found in the file LICENSE in this distribution or at
13 *  http://www.rtems.org/license/LICENSE.
14 */
15
16#include <machine/rtems-bsd-kernel-space.h>
17
18#include <rtems.h>
19#include <rtems/rtems_bsdnet.h>
20#include <bsp.h>
21#include <rtems/bspIo.h>
22#include <libcpu/au1x00.h>
23#include <bsp/irq.h>
24
25#include <stdio.h>
26#include <string.h>
27
28#include <errno.h>
29#include <rtems/error.h>
30
31#include <sys/param.h>
32#include <sys/mbuf.h>
33#include <sys/socket.h>
34#include <sys/sockio.h>
35
36#include <net/if.h>
37
38#include <netinet/in.h>
39#include <netinet/if_ether.h>
40
41#include <assert.h>
42
43#define NUM_IFACES 1
44#define NUM_TX_DMA_BUFS 4
45#define NUM_RX_DMA_BUFS 4
46
47/*  RTEMS event used to start tx daemon. */
48#define START_TX_EVENT  RTEMS_EVENT_1
49/*  RTEMS event used to start rx daemon. */
50#define START_RX_EVENT  RTEMS_EVENT_2
51
52rtems_isr au1x00_emac_isr(rtems_vector_number vector);
53
54#define TX_BUF_SIZE 2048
55
56char tx_buf_base[(4 * TX_BUF_SIZE) + 32];
57
58volatile int wait_count;
59/*
60 * Hardware-specific storage
61 */
62typedef struct
63{
64    /*
65     * Connection to networking code
66     * This entry *must* be the first in the sonic_softc structure.
67     */
68    struct arpcom                    arpcom;
69
70    /*
71     * Interrupt vector
72     */
73    rtems_vector_number             vector;
74
75    /*
76     *  Indicates configuration
77     */
78    int                             acceptBroadcast;
79
80    /*
81     * Tasks waiting for interrupts
82     */
83    rtems_id                        rx_daemon_tid;
84    rtems_id                        tx_daemon_tid;
85
86    /*
87     * Buffers
88     */
89    au1x00_macdma_rx_t             *rx_dma;
90    au1x00_macdma_tx_t             *tx_dma;
91    int                             rx_head;
92    int                             rx_tail;
93    int                             tx_head;
94    int                             tx_tail;
95    struct mbuf                    *rx_mbuf[NUM_RX_DMA_BUFS];
96
97    unsigned char                  *tx_buf[4];
98
99    /*
100     * register addresses
101     */
102    uint32_t                      ctrl_regs;
103    uint32_t                     *en_reg;
104    uint32_t                      int_mask;
105    uint32_t                      int_ctrlr;
106
107    /*
108     * device
109     */
110    int                             unitnumber;
111
112    /*
113     * Statistics
114     */
115    unsigned long                   interrupts;
116    unsigned long                   rx_interrupts;
117    unsigned long                   tx_interrupts;
118    unsigned long                   rx_missed;
119    unsigned long                   rx_bcast;
120    unsigned long                   rx_mcast;
121    unsigned long                   rx_unsupp;
122    unsigned long                   rx_ctrl;
123    unsigned long                   rx_len_err;
124    unsigned long                   rx_crc_err;
125    unsigned long                   rx_dribble;
126    unsigned long                   rx_mii_err;
127    unsigned long                   rx_collision;
128    unsigned long                   rx_too_long;
129    unsigned long                   rx_runt;
130    unsigned long                   rx_watchdog;
131    unsigned long                   rx_pkts;
132    unsigned long                   rx_dropped;
133
134    unsigned long                   tx_deferred;
135    unsigned long                   tx_underrun;
136    unsigned long                   tx_aborted;
137    unsigned long                   tx_pkts;
138} au1x00_emac_softc_t;
139
140static au1x00_emac_softc_t softc[NUM_IFACES];
141
142
143/* function prototypes */
144int rtems_au1x00_emac_attach (struct rtems_bsdnet_ifconfig *config,
145                              int attaching);
146void au1x00_emac_init(void *arg);
147void au1x00_emac_init_hw(au1x00_emac_softc_t *sc);
148void au1x00_emac_start(struct ifnet *ifp);
149void au1x00_emac_stop (au1x00_emac_softc_t *sc);
150void au1x00_emac_tx_daemon (void *arg);
151void au1x00_emac_rx_daemon (void *arg);
152void au1x00_emac_sendpacket (struct ifnet *ifp, struct mbuf *m);
153void au1x00_emac_stats (au1x00_emac_softc_t *sc);
154static int au1x00_emac_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data);
155static void mii_write(au1x00_emac_softc_t *sc, uint8_t reg, uint16_t val);
156static void mii_read(au1x00_emac_softc_t *sc, uint8_t reg, uint16_t *val);
157static void mii_init(au1x00_emac_softc_t *sc);
158
159static void mii_write(au1x00_emac_softc_t *sc, uint8_t reg, uint16_t val)
160{
161    /* wait for the interface to get unbusy */
162    while (AU1X00_MAC_MIICTRL(sc->ctrl_regs) & AU1X00_MAC_MIICTRL_MB) {
163        continue;
164    }
165
166    /* write to address 0 - we only support address 0 */
167    AU1X00_MAC_MIIDATA(sc->ctrl_regs) = val;
168    AU1X00_MAC_MIICTRL(sc->ctrl_regs) = (((reg & 0x1f) << 6) |
169                                         AU1X00_MAC_MIICTRL_MW);
170    au_sync();
171
172    /* wait for it to complete */
173    while (AU1X00_MAC_MIICTRL(sc->ctrl_regs) & AU1X00_MAC_MIICTRL_MB) {
174        continue;
175    }
176}
177
178static void mii_read(au1x00_emac_softc_t *sc, uint8_t reg, uint16_t *val)
179{
180    /* wait for the interface to get unbusy */
181    while (AU1X00_MAC_MIICTRL(sc->ctrl_regs) & AU1X00_MAC_MIICTRL_MB) {
182        continue;
183    }
184
185    /* write to address 0 - we only support address 0 */
186    AU1X00_MAC_MIICTRL(sc->ctrl_regs) = ((reg & 0x1f) << 6);
187    au_sync();
188
189    /* wait for it to complete */
190    while (AU1X00_MAC_MIICTRL(sc->ctrl_regs) & AU1X00_MAC_MIICTRL_MB) {
191        continue;
192    }
193    *val = AU1X00_MAC_MIIDATA(sc->ctrl_regs);
194}
195
196static void mii_init(au1x00_emac_softc_t *sc)
197{
198    uint16_t data;
199
200    mii_write(sc, 0, 0x8000);     /* reset */
201    do {
202        mii_read(sc, 0, &data);
203    } while (data & 0x8000);
204
205    mii_write(sc, 0, 0x3200);     /* reset autonegotiation */
206    mii_write(sc, 17, 0xffc0);    /* setup LEDs */
207
208}
209
210
211
212int rtems_au1x00_emac_attach (
213    struct rtems_bsdnet_ifconfig *config,
214    int attaching
215    )
216{
217    struct ifnet *ifp;
218    int mtu;
219    int unitnumber;
220    char *unitname;
221    static au1x00_emac_softc_t *sc;
222
223    /*
224     * Parse driver name
225     */
226    if ((unitnumber = rtems_bsdnet_parse_driver_name (config, &unitname)) < 0)
227        return 0;
228
229    /*
230     * Is driver free?
231     */
232    if (unitnumber > NUM_IFACES) {
233        printf ("Bad AU1X00 EMAC unit number.\n");
234        return 0;
235    }
236
237    sc = &softc[unitnumber];
238
239    ifp = &sc->arpcom.ac_if;
240    if (ifp->if_softc != NULL) {
241        printf ("Driver already in use.\n");
242        return 0;
243    }
244
245    /*
246     *  zero out the control structure
247     */
248
249    memset((void *)sc, 0, sizeof(*sc));
250
251    sc->unitnumber = unitnumber;
252    sc->int_ctrlr = AU1X00_IC0_ADDR;
253
254    if (unitnumber == 0) {
255        sc->ctrl_regs = AU1100_MAC0_ADDR;
256        sc->en_reg = (void *)(AU1100_MACEN_ADDR + 0);
257
258        sc->tx_dma = (void *)(AU1X00_MACDMA0_ADDR + 0x000);
259        sc->rx_dma = (void *)(AU1X00_MACDMA0_ADDR + 0x100);
260        sc->int_mask = AU1X00_IC_IRQ_MAC0;
261    } else {
262        printk("Unknown network device: %d\n", unitnumber);
263        return 0;
264    }
265
266    /* If the ethernet controller is already set up, read the MAC address */
267    if ((*sc->en_reg & 0x33) == 0x33) {
268        sc->arpcom.ac_enaddr[5] = ((AU1X00_MAC_ADDRHIGH(sc->ctrl_regs) >> 8) &
269                                   0xff);
270        sc->arpcom.ac_enaddr[4] = ((AU1X00_MAC_ADDRHIGH(sc->ctrl_regs) >> 0) &
271                                   0xff);
272        sc->arpcom.ac_enaddr[3] = ((AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 24) &
273                                   0xff);
274        sc->arpcom.ac_enaddr[2] = ((AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 16) &
275                                   0xff);
276        sc->arpcom.ac_enaddr[1] = ((AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 8) &
277                                   0xff);
278        sc->arpcom.ac_enaddr[0] = ((AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 0) &
279                                   0xff);
280    } else {
281        /* It's not set up yet, so we set a MAC address */
282        sc->arpcom.ac_enaddr[5] = 0x05;
283        sc->arpcom.ac_enaddr[4] = 0xc0;
284        sc->arpcom.ac_enaddr[3] = 0x50;
285        sc->arpcom.ac_enaddr[2] = 0x31;
286        sc->arpcom.ac_enaddr[1] = 0x23;
287        sc->arpcom.ac_enaddr[0] = 0x00;
288    }
289
290
291    if (config->mtu) {
292        mtu = config->mtu;
293    } else {
294        mtu = ETHERMTU;
295    }
296
297    sc->acceptBroadcast = !config->ignore_broadcast;
298
299    /*
300     * Set up network interface values
301     */
302    ifp->if_softc = sc;
303    ifp->if_unit = unitnumber;
304    ifp->if_name = unitname;
305    ifp->if_mtu = mtu;
306    ifp->if_init = au1x00_emac_init;
307    ifp->if_ioctl = au1x00_emac_ioctl;
308    ifp->if_start = au1x00_emac_start;
309    ifp->if_output = ether_output;
310    ifp->if_flags = IFF_BROADCAST;
311    if (ifp->if_snd.ifq_maxlen == 0) {
312        ifp->if_snd.ifq_maxlen = ifqmaxlen;
313    }
314
315    /*
316     * Attach the interface
317     */
318    if_attach (ifp);
319    ether_ifattach (ifp);
320    return 1;
321}
322
323void au1x00_emac_init(void *arg)
324{
325    au1x00_emac_softc_t     *sc = arg;
326    struct ifnet *ifp = &sc->arpcom.ac_if;
327
328    /*
329     *This is for stuff that only gets done once (au1x00_emac_init()
330     * gets called multiple times
331     */
332    if (sc->tx_daemon_tid == 0)
333    {
334        /* Set up EMAC hardware */
335        au1x00_emac_init_hw(sc);
336
337
338        /* install the interrupt handler */
339        if (sc->unitnumber == 0) {
340            rtems_interrupt_handler_install(
341              AU1X00_IRQ_MAC0,
342              "NIC0",
343              0,
344              (rtems_interrupt_handler)au1x00_emac_isr,
345              NULL
346            );
347        } else {
348            rtems_interrupt_handler_install(
349              AU1X00_IRQ_MAC1,
350              "NIC1",
351              0,
352              (rtems_interrupt_handler)au1x00_emac_isr,
353              NULL
354            );
355        }
356        AU1X00_IC_MASKCLR(sc->int_ctrlr) = sc->int_mask;
357        au_sync();
358
359        /* set src bit */
360        AU1X00_IC_SRCSET(sc->int_ctrlr) = sc->int_mask;
361
362        /* high level */
363        AU1X00_IC_CFG0SET(sc->int_ctrlr) = sc->int_mask;
364        AU1X00_IC_CFG1CLR(sc->int_ctrlr) = sc->int_mask;
365        AU1X00_IC_CFG2SET(sc->int_ctrlr) = sc->int_mask;
366
367        /* assign to request 0 - negative logic */
368        AU1X00_IC_ASSIGNSET(sc->int_ctrlr) = sc->int_mask;
369        au_sync();
370
371        /* Start driver tasks */
372        sc->tx_daemon_tid = rtems_bsdnet_newproc("ENTx",
373                                                 4096,
374                                                 au1x00_emac_tx_daemon,
375                                                 sc);
376
377        sc->rx_daemon_tid = rtems_bsdnet_newproc("ENRx",
378                                                 4096,
379                                                 au1x00_emac_rx_daemon,
380                                                 sc);
381
382
383    }
384    /* EMAC doesn't support promiscuous, so ignore requests */
385    if (ifp->if_flags & IFF_PROMISC)
386        printf ("Warning - AU1X00 EMAC doesn't support Promiscuous Mode!\n");
387
388    /*
389     * Tell the world that we're running.
390     */
391    ifp->if_flags |= IFF_RUNNING;
392
393    /*
394     * start tx, rx
395     */
396    AU1X00_MAC_CONTROL(sc->ctrl_regs) |= (AU1X00_MAC_CTRL_TE |
397                                             AU1X00_MAC_CTRL_RE);
398    au_sync();
399
400
401} /* au1x00_emac_init() */
402
403void  au1x00_emac_init_hw(au1x00_emac_softc_t *sc)
404{
405    int i;
406    struct mbuf *m;
407    struct ifnet *ifp = &sc->arpcom.ac_if;
408
409    /* reset the MAC */
410    *sc->en_reg = 0x40;
411    au_sync();
412    for (i = 0; i < 10000; i++) {
413        continue;
414    }
415
416/*    *sc->en_reg = AU1X00_MAC_EN_CE; */
417    *sc->en_reg = 41;
418    au_sync();
419    for (i = 0; i < 10000; i++) {
420        continue;
421    }
422
423/*
424    *sc->en_reg = (AU1X00_MAC_EN_CE |
425                   AU1X00_MAC_EN_E2 |
426                   AU1X00_MAC_EN_E1 |
427                   AU1X00_MAC_EN_E0);
428*/
429    *sc->en_reg = 0x33;
430    au_sync();
431    mii_init(sc);
432
433    /* set the mac address */
434    AU1X00_MAC_ADDRHIGH(sc->ctrl_regs) = ((sc->arpcom.ac_enaddr[5] << 8) |
435                                          (sc->arpcom.ac_enaddr[4] << 0));
436    AU1X00_MAC_ADDRLOW(sc->ctrl_regs) = ((sc->arpcom.ac_enaddr[3] << 24) |
437                                         (sc->arpcom.ac_enaddr[2] << 16) |
438                                         (sc->arpcom.ac_enaddr[1] << 8) |
439                                         (sc->arpcom.ac_enaddr[0] << 0));
440
441
442    /* get the MAC address from the chip */
443    sc->arpcom.ac_enaddr[5] = (AU1X00_MAC_ADDRHIGH(sc->ctrl_regs) >> 8) & 0xff;
444    sc->arpcom.ac_enaddr[4] = (AU1X00_MAC_ADDRHIGH(sc->ctrl_regs) >> 0) & 0xff;
445    sc->arpcom.ac_enaddr[3] = (AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 24) & 0xff;
446    sc->arpcom.ac_enaddr[2] = (AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 16) & 0xff;
447    sc->arpcom.ac_enaddr[1] = (AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 8) & 0xff;
448    sc->arpcom.ac_enaddr[0] = (AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 0) & 0xff;
449
450    printk("Setting mac_control to 0x%x\n",
451           (AU1X00_MAC_CTRL_F |
452            AU1X00_MAC_CTRL_PM |
453            AU1X00_MAC_CTRL_RA |
454            AU1X00_MAC_CTRL_DO |
455            AU1X00_MAC_CTRL_EM));
456
457    AU1X00_MAC_CONTROL(sc->ctrl_regs) = (AU1X00_MAC_CTRL_F |   /* full duplex */
458                                         AU1X00_MAC_CTRL_PM |  /* pass mcast */
459                                         AU1X00_MAC_CTRL_RA |  /* recv all */
460                                         AU1X00_MAC_CTRL_DO |  /* disable own */
461                                         AU1X00_MAC_CTRL_EM);  /* Big endian */
462    au_sync();
463    printk("mac_control was set to 0x%x\n", AU1X00_MAC_CONTROL(sc->ctrl_regs));
464    printk("mac_control addr is 0x%x\n", &AU1X00_MAC_CONTROL(sc->ctrl_regs));
465
466    /* initialize our receive buffer descriptors */
467    for (i = 0; i < NUM_RX_DMA_BUFS; i++) {
468        MGETHDR(m, M_WAIT, MT_DATA);
469        MCLGET(m, M_WAIT);
470
471        m->m_pkthdr.rcvif = ifp;
472        m->m_nextpkt = 0;
473
474        /*
475         * The receive buffer must be aligned with a cache line
476         * boundary.
477         */
478        if (mtod(m, uint32_t) & 0x1f) {
479          uint32_t *p = mtod(m, uint32_t *);
480          *p = (mtod(m, uint32_t) + 0x1f) & 0x1f;
481        }
482        sc->rx_dma[i].addr = (mtod(m, uint32_t) & ~0xe0000000);
483        sc->rx_mbuf[i] = m;
484    }
485
486    /* Initialize transmit buffer descriptors */
487    for (i = 0; i < NUM_TX_DMA_BUFS; i++) {
488        sc->tx_dma[i].addr = 0;
489    }
490
491    /* initialize the transmit buffers */
492    sc->tx_buf[0] = (void *)((((int)&tx_buf_base[0]) + 0x1f) & ~0x1f);
493    sc->tx_buf[1] = (void *)(((int)sc->tx_buf[0]) + TX_BUF_SIZE);
494    sc->tx_buf[2] = (void *)(((int)sc->tx_buf[1]) + TX_BUF_SIZE);
495    sc->tx_buf[3] = (void *)(((int)sc->tx_buf[2]) + TX_BUF_SIZE);
496
497    sc->rx_head = (sc->rx_dma[0].addr >> 2) & 0x3;
498    sc->rx_tail = (sc->rx_dma[0].addr >> 2) & 0x3;
499    sc->tx_head = (sc->tx_dma[0].addr >> 2) & 0x3;
500    sc->tx_tail = (sc->tx_dma[0].addr >> 2) & 0x3;
501
502    for (i = 0; i < NUM_RX_DMA_BUFS; i++) {
503        sc->rx_dma[i].addr |= AU1X00_MAC_DMA_RXADDR_EN;
504    }
505
506} /* au1x00_emac_init_hw() */
507
508void au1x00_emac_start(struct ifnet *ifp)
509{
510    au1x00_emac_softc_t *sc = ifp->if_softc;
511
512    rtems_bsdnet_event_send(sc->tx_daemon_tid, START_TX_EVENT);
513    ifp->if_flags |= IFF_OACTIVE;
514}
515
516void au1x00_emac_stop (au1x00_emac_softc_t *sc)
517{
518    struct ifnet *ifp = &sc->arpcom.ac_if;
519
520    ifp->if_flags &= ~IFF_RUNNING;
521
522    /*
523     * Stop the transmitter and receiver.
524     */
525
526    /* Disable TX/RX  */
527    AU1X00_MAC_CONTROL(sc->ctrl_regs) &= ~(AU1X00_MAC_CTRL_TE |
528                                      AU1X00_MAC_CTRL_RE);
529    au_sync();
530}
531
532/*
533 * Driver tx daemon
534 */
535void au1x00_emac_tx_daemon (void *arg)
536{
537    au1x00_emac_softc_t *sc = (au1x00_emac_softc_t *)arg;
538    struct ifnet *ifp = &sc->arpcom.ac_if;
539    struct mbuf *m;
540    rtems_event_set events;
541    uint32_t ic_base;     /* interrupt controller */
542
543    ic_base = AU1X00_IC0_ADDR;
544
545    /* turn on interrupt, then wait for one */
546    if (sc->unitnumber == 0) {
547        AU1X00_IC_MASKSET(ic_base) = AU1X00_IC_IRQ_MAC0;
548    } else {
549        AU1X00_IC_MASKSET(ic_base) = AU1X00_IC_IRQ_MAC1;
550    }
551    au_sync();
552
553    for (;;)
554    {
555        rtems_bsdnet_event_receive(
556            START_TX_EVENT,
557            RTEMS_EVENT_ANY | RTEMS_WAIT,
558            RTEMS_NO_TIMEOUT,
559            &events);
560
561        /* Send packets till queue is empty */
562        for (;;)
563        {
564            /* Get the next mbuf chain to transmit. */
565            IF_DEQUEUE(&ifp->if_snd, m);
566            if (!m)
567                break;
568
569            sc->tx_pkts++;
570            au1x00_emac_sendpacket (ifp, m);
571        }
572        ifp->if_flags &= ~IFF_OACTIVE;
573    }
574}
575
576/*
577 * Driver rx daemon
578 */
579void au1x00_emac_rx_daemon (void *arg)
580{
581    au1x00_emac_softc_t *sc = (au1x00_emac_softc_t *)arg;
582    struct ifnet *ifp = &sc->arpcom.ac_if;
583    struct mbuf *m;
584    struct ether_header *eh;
585    rtems_event_set events;
586    uint32_t status;
587
588    while (1) {
589        rtems_bsdnet_event_receive(
590            START_RX_EVENT,
591            RTEMS_EVENT_ANY | RTEMS_WAIT,
592            RTEMS_NO_TIMEOUT,
593            &events);
594
595        /* while there are packets to receive */
596
597        while (!(sc->rx_dma[sc->rx_head].addr & (AU1X00_MAC_DMA_RXADDR_DN |
598                                                AU1X00_MAC_DMA_RXADDR_EN))) {
599            status = sc->rx_dma[sc->rx_head].stat;
600            if (status & AU1X00_MAC_DMA_RXSTAT_MI) {
601                sc->rx_missed++;
602            }
603            if (status & AU1X00_MAC_DMA_RXSTAT_BF) {
604                sc->rx_bcast++;
605            }
606            if (status & AU1X00_MAC_DMA_RXSTAT_MF) {
607                sc->rx_mcast++;
608            }
609            if (status & AU1X00_MAC_DMA_RXSTAT_UC) {
610                sc->rx_unsupp++;
611            }
612            if (status & AU1X00_MAC_DMA_RXSTAT_CF) {
613                sc->rx_ctrl++;
614            }
615            if (status & AU1X00_MAC_DMA_RXSTAT_LE) {
616                sc->rx_len_err++;
617            }
618            if (status & AU1X00_MAC_DMA_RXSTAT_CR) {
619                sc->rx_crc_err++;
620            }
621            if (status & AU1X00_MAC_DMA_RXSTAT_DB) {
622                sc->rx_dribble++;
623            }
624            if (status & AU1X00_MAC_DMA_RXSTAT_ME) {
625                sc->rx_mii_err++;
626            }
627            if (status & AU1X00_MAC_DMA_RXSTAT_CS) {
628                sc->rx_collision++;
629            }
630            if (status & AU1X00_MAC_DMA_RXSTAT_FL) {
631                sc->rx_too_long++;
632            }
633            if (status & AU1X00_MAC_DMA_RXSTAT_RF) {
634                sc->rx_runt++;
635            }
636            if (status & AU1X00_MAC_DMA_RXSTAT_WT) {
637                sc->rx_watchdog++;
638            }
639
640            /* If no errrors, accept packet */
641            if ((status & (AU1X00_MAC_DMA_RXSTAT_CR |
642                           AU1X00_MAC_DMA_RXSTAT_DB |
643                           AU1X00_MAC_DMA_RXSTAT_RF)) == 0) {
644
645                sc->rx_pkts++;
646
647                /* find the start of the mbuf */
648                m = sc->rx_mbuf[sc->rx_head];
649
650                /* set the length of the mbuf */
651                m->m_len = AU1X00_MAC_DMA_RXSTAT_LEN(sc->rx_dma[sc->rx_head].stat);
652                m->m_len -= 4; /* remove ethernet CRC */
653
654                m->m_pkthdr.len = m->m_len;
655
656                /* strip off the ethernet header from the mbuf */
657                /* but save the pointer to it */
658                eh = mtod (m, struct ether_header *);
659                m->m_data += sizeof(struct ether_header);
660
661                /* give the received packet to the stack */
662                ether_input(ifp, eh, m);
663                /* get a new buf and make it ready for the MAC */
664                MGETHDR(m, M_WAIT, MT_DATA);
665                MCLGET(m, M_WAIT);
666
667                m->m_pkthdr.rcvif = ifp;
668                m->m_nextpkt = 0;
669
670                /*
671                 * The receive buffer must be aligned with a cache line
672                 * boundary.
673                 */
674                {
675                  uint32_t *p = mtod(m, uint32_t *);
676                  *p = (mtod(m, uint32_t) + 0x1f) & ~0x1f;
677                }
678
679            } else {
680                sc->rx_dropped++;
681
682                /* find the mbuf so we can reuse it*/
683                m = sc->rx_mbuf[sc->rx_head];
684            }
685
686            /* set up the receive dma to use the mbuf's cluster */
687            sc->rx_dma[sc->rx_head].addr = (mtod(m, uint32_t) & ~0xe0000000);
688            au_sync();
689            sc->rx_mbuf[sc->rx_head] = m;
690
691            sc->rx_dma[sc->rx_head].addr |= AU1X00_MAC_DMA_RXADDR_EN;
692            au_sync();
693
694
695            /* increment the buffer index */
696            sc->rx_head++;
697            if (sc->rx_head >= NUM_RX_DMA_BUFS) {
698                sc->rx_head = 0;
699            }
700        }
701    }
702}
703
704/* Send packet */
705void au1x00_emac_sendpacket (struct ifnet *ifp, struct mbuf *m)
706{
707    struct mbuf *l = NULL;
708    unsigned int pkt_offset = 0;
709    au1x00_emac_softc_t *sc = (au1x00_emac_softc_t *)ifp->if_softc;
710    uint32_t txbuf;
711
712    /* Wait for EMAC Transmit Queue to become available. */
713    while((sc->tx_dma[sc->tx_head].addr & (AU1X00_MAC_DMA_TXADDR_EN ||
714                                           AU1X00_MAC_DMA_TXADDR_DN)) != 0) {
715        continue;
716    }
717
718    /* copy the mbuf chain into the transmit buffer */
719    l = m;
720
721    txbuf = (uint32_t)sc->tx_buf[sc->tx_head];
722    while (l != NULL)
723    {
724
725        memcpy(((char *)txbuf + pkt_offset), /* offset into pkt for mbuf */
726               (char *)mtod(l, void *),      /* cast to void */
727               l->m_len);                    /* length of this mbuf */
728
729        pkt_offset += l->m_len;              /* update offset */
730        l = l->m_next;                       /* get next mbuf, if any */
731    }
732
733    /* Pad if necessary */
734    if (pkt_offset < 60) {
735        memset((char *)(txbuf + pkt_offset), 0, (60 - pkt_offset));
736        pkt_offset = 60;
737    }
738
739    /* send it off */
740    sc->tx_dma[sc->tx_head].stat = 0;
741    sc->tx_dma[sc->tx_head].len = pkt_offset;
742    sc->tx_dma[sc->tx_head].addr = ((txbuf & ~0xe0000000) |
743                                    AU1X00_MAC_DMA_TXADDR_EN);
744    au_sync();
745
746
747    /*
748     *Without this delay, some outgoing packets never
749     * make it out the device. Nothing in the documentation
750     * explains this.
751     */
752    for (wait_count = 0; wait_count < 5000; wait_count++){
753        continue;
754    }
755
756    /* free the mbuf chain we just copied */
757    m_freem(m);
758
759    sc->tx_head++;
760    if (sc->tx_head >= NUM_TX_DMA_BUFS) {
761        sc->tx_head = 0;
762    }
763
764} /* au1x00_emac_sendpacket () */
765
766
767
768/* Show interface statistics */
769void au1x00_emac_stats (au1x00_emac_softc_t *sc)
770{
771    printf("Interrupts:%-8lu", sc->interrupts);
772    printf("    RX Interrupts:%-8lu", sc->rx_interrupts);
773    printf(" TX Interrupts:%-8lu\n", sc->tx_interrupts);
774    printf("RX Packets:%-8lu", sc->rx_pkts);
775    printf("    RX Control:%-8lu", sc->rx_ctrl);
776    printf("    RX broadcast:%-8lu\n", sc->rx_bcast);
777    printf("RX Mcast:%-8lu", sc->rx_mcast);
778    printf("      RX missed:%-8lu", sc->rx_missed);
779    printf("     RX Unsupported ctrl:%-8lu\n", sc->rx_unsupp);
780    printf("RX Len err:%-8lu", sc->rx_len_err);
781    printf("    RX CRC err:%-8lu", sc->rx_crc_err);
782    printf("    RX dribble:%-8lu\n", sc->rx_dribble);
783    printf("RX MII err:%-8lu", sc->rx_mii_err);
784    printf("    RX collision:%-8lu", sc->rx_collision);
785    printf("  RX too long:%-8lu\n", sc->rx_too_long);
786    printf("RX runt:%-8lu", sc->rx_runt);
787    printf("       RX watchdog:%-8lu", sc->rx_watchdog);
788    printf("   RX dropped:%-8lu\n", sc->rx_dropped);
789
790    printf("TX Packets:%-8lu", sc->tx_pkts);
791    printf("    TX Deferred:%-8lu", sc->tx_deferred);
792    printf("   TX Underrun:%-8lu\n", sc->tx_underrun);
793    printf("TX Aborted:%-8lu\n", sc->tx_aborted);
794
795}
796
797
798/*  Driver ioctl handler */
799static int
800au1x00_emac_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data)
801{
802    au1x00_emac_softc_t *sc = ifp->if_softc;
803    int error = 0;
804
805    switch (command) {
806    case SIOCGIFADDR:
807    case SIOCSIFADDR:
808        ether_ioctl (ifp, command, data);
809        break;
810
811    case SIOCSIFFLAGS:
812        switch (ifp->if_flags & (IFF_UP | IFF_RUNNING))
813        {
814        case IFF_RUNNING:
815            au1x00_emac_stop (sc);
816            break;
817
818        case IFF_UP:
819            au1x00_emac_init (sc);
820            break;
821
822        case IFF_UP | IFF_RUNNING:
823            au1x00_emac_stop (sc);
824            au1x00_emac_init (sc);
825            break;
826
827        default:
828            break;
829        } /* switch (if_flags) */
830        break;
831
832    case SIO_RTEMS_SHOW_STATS:
833        au1x00_emac_stats (sc);
834        break;
835
836        /*
837         * FIXME: All sorts of multicast commands need to be added here!
838         */
839    default:
840        error = EINVAL;
841        break;
842    } /* switch (command) */
843    return error;
844}
845
846/* interrupt handler */
847rtems_isr au1x00_emac_isr (rtems_vector_number v)
848{
849    volatile au1x00_emac_softc_t *sc;
850    int tx_flag = 0;
851    int rx_flag = 0;
852
853    sc = &softc[0];
854    if (v != AU1X00_IRQ_MAC0) {
855      assert(v == AU1X00_IRQ_MAC0);
856    }
857
858    sc->interrupts++;
859
860    /*
861     * Since there's no easy way to find out the source of the
862     * interrupt, we have to look at the tx and rx dma buffers
863     */
864    /* receive interrupt */
865    while(sc->rx_dma[sc->rx_tail].addr & AU1X00_MAC_DMA_RXADDR_DN) {
866        rx_flag = 1;
867        sc->rx_interrupts++;
868        sc->rx_dma[sc->rx_tail].addr &= ~AU1X00_MAC_DMA_RXADDR_DN;
869        au_sync();
870
871        sc->rx_tail++;
872        if (sc->rx_tail >= NUM_RX_DMA_BUFS) {
873            sc->rx_tail = 0;
874        }
875    }
876    if (rx_flag != 0) {
877        rtems_bsdnet_event_send(sc->rx_daemon_tid, START_RX_EVENT);
878    }
879
880    /* transmit interrupt */
881    while (sc->tx_dma[sc->tx_tail].addr & AU1X00_MAC_DMA_TXADDR_DN) {
882        uint32_t status;
883        tx_flag = 1;
884        sc->tx_interrupts++;
885
886        status = sc->tx_dma[sc->tx_tail].stat;
887        if (status & AU1X00_MAC_DMA_TXSTAT_DF) {
888            sc->tx_deferred++;
889        }
890        if (status & AU1X00_MAC_DMA_TXSTAT_UR) {
891            sc->tx_underrun++;
892        }
893        if (status & AU1X00_MAC_DMA_TXSTAT_FA) {
894            sc->tx_aborted++;
895        }
896
897        sc->tx_dma[sc->tx_tail].addr = 0;
898        au_sync();
899
900        sc->tx_tail++;
901        if (sc->tx_tail >= NUM_TX_DMA_BUFS) {
902            sc->tx_tail = 0;
903        }
904    }
905    if (tx_flag != 0) {
906        rtems_bsdnet_event_send(sc->tx_daemon_tid, START_TX_EVENT);
907    }
908}
909
Note: See TracBrowser for help on using the repository browser.