source: rtems/c/src/lib/libbsp/mips/csb350/network/network.c @ 650a6e7f

4.104.114.84.95
Last change on this file since 650a6e7f was 650a6e7f, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 14, 2005 at 11:41:57 PM

2005-03-14 Joel Sherrill <joel@…>

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