source: rtems/c/src/lib/libbsp/powerpc/mvme2307/network/network.c @ 19ca797

4.104.114.84.95
Last change on this file since 19ca797 was 19ca797, checked in by Joel Sherrill <joel.sherrill@…>, on 10/04/99 at 20:41:28

Motorola MVME2307 BSP submitted by Jay Kulpinski <jskulpin@…>.
No modifications made.

  • Property mode set to 100644
File size: 25.3 KB
Line 
1/*
2 * RTEMS driver for TULIP based Ethernet Controller
3 *
4 *  $Header$
5 */
6
7
8
9/* make sure we can identify the platform (is __i386 valid?) */
10#if !defined(__PPC) && !defined(__i386)
11#   error "unknown platform:  should be __i386 or __PPC"
12#endif
13
14
15#include <bsp.h>
16#if defined(i386)
17#include <pcibios.h>
18#endif
19
20#include <stdlib.h>
21#include <stdio.h>
22#include <stdarg.h>
23#include <rtems/error.h>
24#include <rtems/rtems_bsdnet.h>
25
26#include <rtems/score/cpu.h>
27
28#include <sys/param.h>
29#include <sys/mbuf.h>
30
31#include <sys/socket.h>
32#include <sys/sockio.h>
33#include <net/if.h>
34#include <netinet/in.h>
35#include <netinet/if_ether.h>
36 
37#if defined(i386)
38#include <irq.h>
39#endif
40
41#ifdef malloc
42#undef malloc
43#endif
44#ifdef free
45#undef free
46#endif
47
48#define PCI_VENDOR_ID_DEC 0x1011
49#define PCI_DEVICE_ID_DEC_TULIP_FAST 0x0009
50
51#define IO_MASK  0x3
52#define MEM_MASK  0xF
53
54/* command and status registers, 32-bit access, only if MEMORY-ACCESS */
55#define CSR0  0x00  /* bus mode register */
56#define CSR1  0x02  /* transmit poll demand */
57#define CSR2  0x04  /* receive poll demand */
58#define CSR3  0x06  /* receive list base address */
59#define CSR4  0x08  /* transmit list base address */
60#define CSR5  0x0A  /* status register */
61#define CSR6  0x0C  /* operation mode register */
62#define CSR7  0x0E  /* interrupt mask register */
63#define CSR8  0x10  /* missed frame counter */
64#define CSR9  0x12  /* Ethernet ROM register */
65#define CSR10 0x14  /* reserved */
66#define CSR11 0x16  /* full-duplex register */
67#define CSR12 0x18  /* SIA status register */
68#define CSR13 0x1A
69#define CSR14 0x1C
70#define CSR15 0x1E  /* SIA general register */
71
72#define DEC_REGISTER_SIZE    0x100   /* to reserve virtual memory */
73
74#define RESET_CHIP   0x00000001
75#if defined(__PPC)
76#define CSR0_MODE    0x0020E002   
77#define CSR6_INIT    0x0224c000   
78#else
79#define CSR0_MODE    0x01a08000   
80#define CSR6_INIT    0x020c0000   
81#endif
82#define ROM_ADDRESS  0x00004800
83#define CSR6_TX      0x00002000   
84#define CSR6_TXRX    0x00002002   
85#define IT_SETUP     0x0001a3ef   
86#define CLEAR_IT     0xFFFFFFFF   
87#define NO_IT        0x00000000   
88
89#define SETUP_PACKET      0x08000000
90#define END_OF_RING       0x02000000
91#define CHAINED_ADDRESS   0x01000000
92#define OWNED_BY_DEC21140 0x80000000
93#define OWNED_BY_HOST     0x00000000
94#define LAST_SEGMENT      0x40000000
95#define FIRST_SEGMENT     0x20000000
96
97#define NRXBUFS 8   /* number of receive buffers */
98#define NTXBUFS 32  /* number of transmit buffers */
99
100/* message descriptor entry */
101struct MD {
102    /* used by hardware */
103    volatile unsigned32 status;
104    volatile unsigned32 counts;
105    unsigned32 buf1, buf2; 
106    /* used by software */
107    struct mbuf *m;
108    struct MD *next;
109};
110
111static inline void write_descr_status(volatile struct MD *m, unsigned32 status) {
112    st_le32(&(m->status), status);
113}
114
115static inline unsigned32 read_descr_status(volatile struct MD *m) {
116    return ld_le32(&(m->status));
117}
118
119static inline void write_descr_counts(volatile struct MD *m, unsigned32 counts) {
120    st_le32(&(m->counts), counts);
121}
122
123static inline unsigned32 read_descr_counts(volatile struct MD *m) {
124    return ld_le32(&(m->counts));
125}
126
127static inline void set_chain_address(volatile struct MD *m, void *addr) {
128    st_le32(&(m->buf2), LOCAL_TO_PCI(addr));
129}
130
131static inline void set_buffer_address(volatile struct MD *m, void *addr) {
132    st_le32(&(m->buf1), LOCAL_TO_PCI(addr));
133}
134
135static inline void *get_buffer_address(volatile struct MD *m) {
136    return (void *)INVERSE_LOCAL_TO_PCI(ld_le32(&(m->buf1)));
137}
138
139/*
140 * Number of WDs supported by this driver
141 */
142#define NDECDRIVER  1
143
144/*
145 * Receive buffer size -- Allow for a full ethernet packet including CRC
146 */
147#define RBUF_SIZE   1520
148
149#define ET_MINLEN 60        /* minimum message length */
150
151/*
152 * RTEMS event used by interrupt handler to signal driver tasks.
153 * This must not be any of the events used by the network task synchronization.
154 */
155#define INTERRUPT_EVENT RTEMS_EVENT_1
156
157/*
158 * RTEMS event used to start transmit daemon.
159 * This must not be the same as INTERRUPT_EVENT.
160 */
161#define START_TRANSMIT_EVENT    RTEMS_EVENT_2
162
163#if (MCLBYTES < RBUF_SIZE)
164# error "Driver must have MCLBYTES > RBUF_SIZE"
165#endif
166
167/*
168 * Per-device data
169 */
170struct dec21140_softc {
171    struct arpcom           arpcom;
172#if defined(__PPC)
173    int         irqInfo;
174#else
175    rtems_irq_connect_data  irqInfo;
176#endif
177    struct MD   *MDbase;
178    char        *bufferBase;
179    int         acceptBroadcast;
180    rtems_id    rxDaemonTid;
181    rtems_id    txDaemonTid;
182
183    struct MD   *TxMD;
184    struct MD   *SentTxMD;
185    int         PendingTxCount;
186    int         TxSuspended;
187
188    unsigned32  port;
189    unsigned32  *base;
190
191    /*
192    * Statistics
193    */
194    unsigned32  rxInterrupts;
195    unsigned32  rxNotFirst;
196    unsigned32  rxNotLast;
197    unsigned32  rxGiant;
198    unsigned32  rxNonOctet;
199    unsigned32  rxRunt;
200    unsigned32  rxBadCRC;
201    unsigned32  rxOverrun;
202    unsigned32  rxCollision;
203
204    unsigned32  txInterrupts;
205    unsigned32  txDeferred;
206    unsigned32  txHeartbeat;
207    unsigned32  txLateCollision;
208    unsigned32  txRetryLimit;
209    unsigned32  txUnderrun;
210    unsigned32  txLostCarrier;
211    unsigned32  txRawWait;
212};
213
214static struct dec21140_softc dec21140_softc[NDECDRIVER];
215static rtems_interval ticks_per_second;
216
217/* ================================================================ */
218
219static inline void write_csr(unsigned32 *base, int csr, unsigned32 value) {
220    synchronize_io();
221    st_le32(base + csr, value);
222}
223
224static inline unsigned32 read_csr(unsigned32 *base, int csr) {
225    synchronize_io();
226    return ld_le32(base + csr);
227}
228
229
230
231
232/* ================================================================ */
233
234/*
235 * DEC21140 interrupt handler
236 */
237static rtems_isr dec21140Enet_interrupt_handler (rtems_vector_number v) {
238    unsigned32 *tbase;
239    unsigned32 status;
240    struct dec21140_softc *sc;
241
242#if NDECDRIVER == 1
243    sc = &dec21140_softc[0];
244#else
245#   error "need to find dec21140_softc[i] based on vector number"
246#endif
247    tbase = sc->base ;
248
249    /*
250     * Read status
251     */
252    status = read_csr(tbase, CSR5);
253    write_csr(tbase, CSR5, status);  /* clear the bits we've read */
254
255    /*
256     * severe error?
257     */
258    if (status & 0x0000230a){
259        printk("FATAL ERROR in network driver:  CSR5=0x%08x\n", status);
260    }
261    /*
262     * Frame received?
263     */
264    if (status & 0x000000c0){
265        sc->rxInterrupts++;
266        rtems_event_send (sc->rxDaemonTid, INTERRUPT_EVENT);
267    }
268
269    /*
270     * Frame transmitted or transmit error?
271     */
272    if (status & 0x00000025) {
273        if (status & 0x00000004) {
274            sc->TxSuspended = 1;
275        }
276        sc->txInterrupts++;
277        rtems_event_send (sc->txDaemonTid, INTERRUPT_EVENT);
278    }
279}
280
281#if defined(__i386)
282static void nopOn(const rtems_irq_connect_data* notUsed) {
283    /*
284     * code should be moved from dec21140Enet_initialize_hardware
285     * to this location
286     */
287}
288
289static int dec21140IsOn(const rtems_irq_connect_data* irq) {
290    return BSP_irq_enabled_at_i8259s (irq->name);
291}
292#endif
293
294
295/*
296 * Initialize the ethernet hardware
297 */
298#define PPCBUG_HW_ADDR_STORAGE 0x1f2c
299static void dec21140Enet_initialize_hardware (struct dec21140_softc *sc) {
300    rtems_status_code st;
301    unsigned32 *tbase;
302    int i;
303    char *cp, *setup_frm, *eaddrs;
304    unsigned char *buffer;
305    struct MD *rmd;
306
307
308    tbase = sc->base;
309
310    /*
311     * WARNING : First write in CSR6
312     *           Then Reset the chip ( 1 in CSR0)
313     */
314
315    write_csr(tbase, CSR6, CSR6_INIT); 
316    write_csr(tbase, CSR0, RESET_CHIP); 
317    delay_in_bus_cycles(200);
318
319    /*
320     * Init CSR0
321     */
322    write_csr(tbase, CSR0, CSR0_MODE); 
323
324    read_nvram(sc->arpcom.ac_enaddr, PPCBUG_HW_ADDR_STORAGE, 6);
325 
326#ifdef DEC_DEBUG
327    printk("DC21140 %x:%x:%x:%x:%x:%x IRQ %d IO %x M %x .........\n",
328            sc->arpcom.ac_enaddr[0], sc->arpcom.ac_enaddr[1],
329            sc->arpcom.ac_enaddr[2], sc->arpcom.ac_enaddr[3],
330            sc->arpcom.ac_enaddr[4], sc->arpcom.ac_enaddr[5],
331            sc->irqInfo, sc->port, sc->base);
332#endif
333 
334    /*
335     * Init RX ring
336     */
337
338#if defined(__i386)
339    cp = (char *)malloc((NRXBUFS + NTXBUFS) * (sizeof(struct MD) + RBUF_SIZE) +
340                        PG_SIZE);
341    sc->bufferBase = cp;
342    cp += (PG_SIZE - (int)cp) & MASK_OFFSET ;
343    if (_CPU_is_paging_enabled()) {
344        _CPU_change_memory_mapping_attribute
345                (NULL, cp,
346                (NRXBUFS + NTXBUFS) * (sizeof(struct MD) + RBUF_SIZE),
347                PTE_CACHE_DISABLE | PTE_WRITABLE);
348    }
349#endif
350#if defined(__PPC)
351    cp = (char *)malloc((NRXBUFS + NTXBUFS)*(sizeof(struct MD)+ RBUF_SIZE) +
352                        4096);
353#endif
354    rmd = (struct MD *)cp;
355    sc->MDbase = rmd;
356    buffer = cp + ((NRXBUFS + NTXBUFS)*sizeof(struct MD));
357
358    write_csr(tbase, CSR3, LOCAL_TO_PCI(sc->MDbase));
359    for (i = 0 ; i < NRXBUFS; i++){
360        struct mbuf *m;
361       
362        /* allocate an mbuf for each receive descriptor */
363        MGETHDR (m, M_WAIT, MT_DATA);
364        MCLGET (m, M_WAIT);
365        m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
366        rmd->m = m;
367
368        set_buffer_address(rmd, mtod(m, void *));
369        if (i == NRXBUFS - 1) {
370            write_descr_counts(rmd, END_OF_RING | RBUF_SIZE);
371            rmd->next = sc->MDbase;
372        } else {
373            write_descr_counts(rmd, CHAINED_ADDRESS | RBUF_SIZE);
374            set_chain_address(rmd, rmd + 1);
375            rmd->next = rmd + 1;
376        }
377        write_descr_status(rmd, OWNED_BY_DEC21140);
378        rmd++;
379    }
380
381    /*
382     * Init TX ring
383     */
384    write_csr(tbase, CSR4, LOCAL_TO_PCI(rmd));
385    for (i = 0 ; i < NTXBUFS; i++){
386        set_buffer_address(rmd + i, buffer + NRXBUFS * RBUF_SIZE + i * RBUF_SIZE);
387        write_descr_counts(rmd + i, FIRST_SEGMENT | LAST_SEGMENT | CHAINED_ADDRESS);
388        if (i == NTXBUFS - 1) {
389            set_chain_address(rmd + i, rmd);
390            (rmd + i)->next = rmd;
391        } else {
392            set_chain_address(rmd + i, rmd + i + 1);
393            (rmd + i)->next = rmd + i + 1;
394        }
395        write_descr_status(rmd + i, OWNED_BY_HOST);
396    }
397
398#if defined(__i386)
399    sc->irqInfo.hdl = (rtems_irq_hdl)dec21140Enet_interrupt_handler;
400    sc->irqInfo.on  = nopOn;
401    sc->irqInfo.off = nopOn;
402    sc->irqInfo.isOn = dec21140IsOn; 
403    st = BSP_install_rtems_irq_handler (&sc->irqInfo);
404    if (!st) {
405        rtems_panic ("Can't attach DEC21140 interrupt handler for irq %d\n",
406                        sc->irqInfo.name);
407    }
408#endif
409#if defined(__PPC)
410    {
411        rtems_isr_entry old_handler;
412
413        st = bsp_interrupt_catch(dec21140Enet_interrupt_handler,
414                                 IRQ_ETHERNET, &old_handler);
415        if (st != RTEMS_SUCCESSFUL) {
416            rtems_panic("Can't attach DEC21140 interrupt handler\n");
417        }
418        bsp_interrupt_enable(IRQ_ETHERNET, PRIORITY_ISA_INT);
419    }
420#endif
421
422    /* no interrupts for now */
423    write_csr(tbase, CSR7, NO_IT);
424
425    /*
426     * Build setup frame
427     */
428    setup_frm = get_buffer_address(rmd);
429    eaddrs = (char *)(sc->arpcom.ac_enaddr);
430    /* Fill the buffer with our physical address. */
431    for (i = 1; i < 16; i++) {
432        *setup_frm++ = eaddrs[0];
433        *setup_frm++ = eaddrs[1];
434        setup_frm += 2;
435        *setup_frm++ = eaddrs[2];
436        *setup_frm++ = eaddrs[3];
437        setup_frm += 2;
438        *setup_frm++ = eaddrs[4];
439        *setup_frm++ = eaddrs[5];
440        setup_frm += 2;
441    }
442    /* Add the broadcast address when doing perfect filtering */
443    memset((char*)setup_frm, 0xff, 12);
444    write_descr_counts(rmd, SETUP_PACKET | CHAINED_ADDRESS | 192);
445    write_descr_status(rmd, OWNED_BY_DEC21140);
446    /*
447     * Start TX for setup frame
448     */
449    write_csr(tbase, CSR6, CSR6_INIT | CSR6_TX);
450
451    write_csr(tbase, CSR1, 1);
452    while (read_descr_status(rmd) & OWNED_BY_DEC21140);
453    sc->SentTxMD = sc->TxMD = rmd + 1;
454    sc->PendingTxCount = 0;
455    sc->TxSuspended = 1;
456    /*
457     * Set up interrupts
458     */
459    write_csr(tbase, CSR5, IT_SETUP);
460    write_csr(tbase, CSR7, IT_SETUP);
461
462    /*
463     * Enable RX and TX
464     */
465    write_csr(tbase, CSR6, CSR6_INIT | CSR6_TXRX);
466
467}
468
469static void dec21140_rxDaemon (void *arg) {
470    unsigned32 *tbase;
471    struct dec21140_softc *sc = arg;
472    struct ifnet *ifp = &sc->arpcom.ac_if;
473    struct MD *rmd;
474    unsigned32 len;
475    unsigned32 rx_status;
476    rtems_event_set events;
477
478    tbase = sc->base;
479    rmd = sc->MDbase;
480
481    for (;;){
482
483        rtems_bsdnet_event_receive (INTERRUPT_EVENT,
484                                    RTEMS_WAIT | RTEMS_EVENT_ANY,
485                                    RTEMS_NO_TIMEOUT,
486                                    &events);
487        while (((rx_status = read_descr_status(rmd)) & OWNED_BY_DEC21140) == 0) {
488            struct ether_header *eh;
489            struct mbuf *m = rmd->m;
490           
491            /*
492             *  packet is good if Error Summary = 0 and First Descriptor = 1
493             *  and Last Descriptor = 1
494             */
495            if ((rx_status & 0x00008300) == 0x00000300) {
496                /* pass on the packet in the mbuf */
497                len = (rx_status >> 16) & 0x7ff;
498                m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header);
499                eh = mtod (m, struct ether_header *);
500                m->m_data += sizeof(struct ether_header);
501                ether_input (ifp, eh, m);
502
503                /* get a new mbuf for the 21140 */
504                MGETHDR (m, M_WAIT, MT_DATA);
505                MCLGET (m, M_WAIT);
506                m->m_pkthdr.rcvif = ifp;
507                rmd->m = m;
508                set_buffer_address(rmd, mtod(m, void *));
509            } else {
510                if ((rx_status & (1 << 9)) == 0) {
511                    sc->rxNotFirst++;
512                }
513                if ((rx_status & (1 << 8)) == 0) {
514                    sc->rxNotLast++;
515                }
516                if (rx_status & (1 << 7)) {
517                    sc->rxGiant++;
518                }
519                if (rx_status & (1 << 2)) {
520                    sc->rxNonOctet++;
521                }
522                if (rx_status & (1 << 11)) {
523                    sc->rxRunt++;
524                }
525                if (rx_status & (1 << 1)) {
526                    sc->rxBadCRC++;
527                }
528                if (rx_status & (1 << 14)) {
529                    sc->rxOverrun++;
530                }
531                if (rx_status & (1 << 6)) {
532                    sc->rxCollision++;
533                }
534            }
535           
536            /* give the descriptor back to the 21140 */
537            write_descr_status(rmd, OWNED_BY_DEC21140);
538
539            /* check for more ready descriptors */
540            rmd = rmd->next;
541        }
542    }
543}
544
545static void reap_sent_descriptors(struct dec21140_softc *sc) {
546    struct MD *descr = sc->SentTxMD;
547    unsigned32 *tbase = sc->base;
548    unsigned32 tx_status = 0;
549    struct mbuf *m, *n;
550
551    while (sc->PendingTxCount > 0 &&
552          ((tx_status = read_descr_status(descr)) & OWNED_BY_DEC21140) == 0 ) {
553        for (m = descr->m; m; m = n) {
554            MFREE(m, n);
555        }
556        if (read_descr_counts(descr) & LAST_SEGMENT) {
557            if (tx_status & (1 << 0)) {
558                sc->txDeferred++;
559            }
560            if (tx_status & (1 << 7)) {
561                sc->txHeartbeat++;
562            }
563            if (tx_status & (1 << 9)) {
564                sc->txLateCollision++;
565            }
566            if (tx_status & (1 << 8)) {
567                sc->txRetryLimit++;
568            }
569            if (tx_status & (1 << 1)) {
570                sc->txUnderrun++;
571                write_csr(tbase, CSR1, 0x1); /* restart transmitter */
572                /* this shouldn't happen - descriptor should still be
573                   owned by 21140 */
574                printk("ethernet chip underrun error\n");
575            }
576            if (tx_status & (1 << 10)) {
577                sc->txLostCarrier++;
578            }
579        }
580        descr = descr->next;
581        sc->PendingTxCount--;
582    }
583    sc->SentTxMD = descr;
584    /* check for Underflow and restart transmission */
585    if ((tx_status & 0x80000002) == 0x80000002) {
586        sc->txUnderrun++;
587        write_csr(tbase, CSR1, 0x1); /* restart transmitter */
588        printk("ethernet chip underrun error\n");
589    }
590}
591
592static void sendpacket (volatile struct ifnet *ifp, struct mbuf *m) {
593    struct mbuf *mbuf = m;
594    struct dec21140_softc *sc = ifp->if_softc;
595    struct MD *descr, *first, *last;
596    unsigned32 *tbase = sc->base;
597    int count = 0;
598
599    first = last = descr = sc->TxMD;
600    reap_sent_descriptors(sc);
601    while (mbuf) {
602        if (mbuf->m_len) {
603            /* if no descriptor is available, wait for interrupt */
604            while ((sc->PendingTxCount + count) == NTXBUFS) {
605                rtems_event_set events;
606                rtems_status_code result;
607
608                if (sc->PendingTxCount == 0) {
609                    printk("ERROR: too many segments to transmit in mbuf\n");
610                }
611                result = rtems_bsdnet_event_receive(INTERRUPT_EVENT,
612                                                   RTEMS_WAIT | RTEMS_EVENT_ANY,
613                                                   20 * ticks_per_second,
614                                                   &events);
615                if (result == RTEMS_TIMEOUT) {
616                    printk("still waiting for tx descriptor in sendpacket\n");
617                }
618                reap_sent_descriptors(sc);
619                if (sc->TxSuspended) {
620                    sc->TxSuspended = 0;
621                    write_csr(tbase, CSR1, 0x1);
622                }
623            }
624            set_buffer_address(descr, mtod (mbuf, void *));
625            write_descr_counts(descr, CHAINED_ADDRESS | mbuf->m_len);
626            last = descr;
627            if (descr != first) {
628                write_descr_status(descr, OWNED_BY_DEC21140);
629            }
630            descr->m = 0;
631            count++;
632            descr = descr->next;
633        }
634        mbuf = mbuf->m_next;
635    }
636    write_descr_counts(first, read_descr_counts(first) | FIRST_SEGMENT);
637    write_descr_counts(last, read_descr_counts(last) | LAST_SEGMENT);
638    last->m = m;
639    sc->TxMD = descr;
640    synchronize_io();
641    write_descr_status(first, OWNED_BY_DEC21140);
642    sc->PendingTxCount += count;
643    if (sc->TxSuspended) {
644        sc->TxSuspended = 0;
645        synchronize_io();
646        write_csr(tbase, CSR1, 0x1);
647    }
648}
649
650/*
651 * Driver transmit daemon
652 */
653static void dec21140_txDaemon (void *arg) {
654    struct dec21140_softc *sc = (struct dec21140_softc *)arg;
655    volatile struct ifnet *ifp = &sc->arpcom.ac_if;
656    unsigned32 *tbase = sc->base;
657    struct mbuf *m;
658    rtems_event_set events;
659
660    for (;;) {
661        /*
662         * Wait for packet
663         */
664
665        rtems_bsdnet_event_receive (START_TRANSMIT_EVENT,
666                                    RTEMS_EVENT_ANY | RTEMS_WAIT,
667                                    RTEMS_NO_TIMEOUT, &events);
668
669        /*
670         * Send packets till queue is empty
671         */
672        for (;;) {
673            /*
674             * Get the next mbuf chain to transmit.
675             */
676            IF_DEQUEUE(&ifp->if_snd, m);
677            if (!m) {
678                break;
679            }
680            sendpacket (ifp, m);
681        }
682        ifp->if_flags &= ~IFF_OACTIVE;
683    }
684}   
685
686
687static void dec21140_start (struct ifnet *ifp) {
688    struct dec21140_softc *sc = ifp->if_softc;
689
690    ifp->if_flags |= IFF_OACTIVE;
691    rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
692}
693
694/*
695 * Initialize and start the device
696 */
697static void dec21140_init (void *arg) {
698    struct dec21140_softc *sc = arg;
699    struct ifnet *ifp = &sc->arpcom.ac_if;
700
701    if (sc->txDaemonTid == 0) {
702
703        /*
704         * Set up DEC21140 hardware
705         */
706        dec21140Enet_initialize_hardware (sc);
707
708        /*
709         * Start driver tasks
710         */
711#if NDECDRIVER == 1
712        sc->rxDaemonTid = rtems_bsdnet_newproc ("DCrx", 4096,
713                                                dec21140_rxDaemon, sc);
714        sc->txDaemonTid = rtems_bsdnet_newproc ("DCtx", 4096,
715                                                dec21140_txDaemon, sc);
716#else
717#   error "need to fix task IDs"
718#endif
719    }
720
721    /*
722    * Tell the world that we're running.
723    */
724    ifp->if_flags |= IFF_RUNNING;
725
726}
727
728/*
729 * Stop the device
730 */
731static void dec21140_stop (struct dec21140_softc *sc) {
732    unsigned32 *tbase;
733    struct ifnet *ifp = &sc->arpcom.ac_if;
734
735    ifp->if_flags &= ~IFF_RUNNING;
736
737    /*
738     * Stop the transmitter
739     */
740    tbase = sc->base;
741    write_csr(tbase, CSR7, NO_IT);
742    write_csr(tbase, CSR6, CSR6_INIT);
743    free(sc->bufferBase);
744}
745
746
747/*
748 * Show interface statistics
749 */
750static void dec21140_stats (struct dec21140_softc *sc) {
751    printf ("      Rx Interrupts:%-8u", sc->rxInterrupts);
752    printf ("       Not First:%-8u", sc->rxNotFirst);
753    printf ("        Not Last:%-8u\n", sc->rxNotLast);
754    printf ("              Giant:%-8u", sc->rxGiant);
755    printf ("            Runt:%-8u", sc->rxRunt);
756    printf ("       Non-octet:%-8u\n", sc->rxNonOctet);
757    printf ("            Bad CRC:%-8u", sc->rxBadCRC);
758    printf ("         Overrun:%-8u", sc->rxOverrun);
759    printf ("       Collision:%-8u\n", sc->rxCollision);
760
761    printf ("      Tx Interrupts:%-8u", sc->txInterrupts);
762    printf ("        Deferred:%-8u", sc->txDeferred);
763    printf (" Missed Hearbeat:%-8u\n", sc->txHeartbeat);
764    printf ("         No Carrier:%-8u", sc->txLostCarrier);
765    printf ("Retransmit Limit:%-8u", sc->txRetryLimit);
766    printf ("  Late Collision:%-8u\n", sc->txLateCollision);
767    printf ("           Underrun:%-8u", sc->txUnderrun);
768    printf (" Raw output wait:%-8u\n", sc->txRawWait);
769}
770
771/*
772 * Driver ioctl handler
773 */
774static int dec21140_ioctl (struct ifnet *ifp, int command, caddr_t data) {
775    struct dec21140_softc *sc = ifp->if_softc;
776    int error = 0;
777
778    switch (command) {
779    case SIOCGIFADDR:
780    case SIOCSIFADDR:
781        ether_ioctl (ifp, command, data);
782        break;
783
784    case SIOCSIFFLAGS:
785        switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
786        case IFF_RUNNING:
787            dec21140_stop (sc);
788            break;
789
790        case IFF_UP:
791            dec21140_init (sc);
792            break;
793
794        case IFF_UP | IFF_RUNNING:
795            dec21140_stop (sc);
796            dec21140_init (sc);
797            break;
798
799        default:
800            break;
801        }
802        break;
803
804    case SIO_RTEMS_SHOW_STATS:
805        dec21140_stats (sc);
806        break;
807       
808    /*
809     * FIXME: All sorts of multicast commands need to be added here!
810     */
811    default:
812        error = EINVAL;
813        break;
814    }
815    return error;
816}
817
818/*
819 * Attach an DEC21140 driver to the system
820 */
821int rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config) {
822    struct dec21140_softc *sc;
823    struct ifnet *ifp;
824    int mtu;
825    int i;
826#if defined(__i386)
827    int signature;
828    int value;
829    char interrupt;
830    int diag;
831   
832    /*
833     * Initialise PCI module
834     */
835    if (pcib_init() == PCIB_ERR_NOTPRESENT) {
836        rtems_panic("PCI BIOS not found !!");
837    }
838   
839    /*
840     * First, find a DEC board
841     */
842    if ((diag = pcib_find_by_devid(PCI_VENDOR_ID_DEC,
843                       PCI_DEVICE_ID_DEC_TULIP_FAST,
844                       0,
845                       &signature)) != PCIB_ERR_SUCCESS) {
846        rtems_panic("DEC PCI board not found !! (%d)\n", diag);
847    } else {
848        printk("DEC PCI Device found\n");
849    }
850#endif
851#if defined(__PPC)
852    int sig;
853
854    /* search PCI bus for Tulip chip */
855    sig = pci_find_by_devid(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST, 0);
856    if (sig == PCI_NOT_FOUND) {
857        printk("PCI scan failed:  DEC 21140 not found\n");
858        return 0;
859    }
860
861#endif
862   
863    /*
864     * Find a free driver
865     */
866    for (i = 0 ; i < NDECDRIVER ; i++) {
867        sc = &dec21140_softc[i];
868        ifp = &sc->arpcom.ac_if;
869        if (ifp->if_softc == NULL) {
870            break;
871        }
872    }
873    if (i >= NDECDRIVER) {
874        printk ("Too many DEC drivers.\n");
875        return 0;
876    }
877
878    /*
879     * Process options
880     */
881
882    sc->port = pci_conf_read32(sig, PCI_BASE_ADDRESS_0) & ~IO_MASK;
883    sc->base = (void *)
884           PCI_TO_LOCAL(pci_conf_read32(sig, PCI_BASE_ADDRESS_1) & ~MEM_MASK);
885    sc->irqInfo = pci_conf_read8(sig, 60);
886#if defined(__i386)
887    pcib_conf_read32(signature, 16, &value);
888    sc->port = value & ~IO_MASK;
889       
890    pcib_conf_read32(signature, 20, &value);
891    if (_CPU_is_paging_enabled()) {
892        _CPU_map_phys_address(&(sc->base),
893                (void *)(value & ~MEM_MASK),
894                DEC_REGISTER_SIZE ,
895                PTE_CACHE_DISABLE | PTE_WRITABLE);
896    } else {
897        sc->base = (unsigned32 *)(value & ~MEM_MASK);
898    }
899   
900    pcib_conf_read8(signature, 60, &interrupt);
901    sc->irqInfo.name = (rtems_irq_symbolic_name)interrupt;
902#endif
903   
904    if (config->hardware_address) {
905        memcpy(sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
906    } else {
907        memset (sc->arpcom.ac_enaddr, 0x08, ETHER_ADDR_LEN);
908    }
909    if (config->mtu) {
910        mtu = config->mtu;
911    } else {
912        mtu = ETHERMTU;
913    }
914
915    sc->acceptBroadcast = !config->ignore_broadcast;
916
917    /*
918     * Set up network interface values
919     */
920    ifp->if_softc = sc;
921    ifp->if_unit = i + 1;
922    ifp->if_name = "dc";
923    ifp->if_mtu = mtu;
924    ifp->if_init = dec21140_init;
925    ifp->if_ioctl = dec21140_ioctl;
926    ifp->if_start = dec21140_start;
927    ifp->if_output = ether_output;
928    ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
929    if (ifp->if_snd.ifq_maxlen == 0) {
930        ifp->if_snd.ifq_maxlen = ifqmaxlen;
931    }
932
933    /*
934     * Attach the interface
935     */
936    if_attach (ifp);
937    ether_ifattach (ifp);
938
939    /*
940     * Determine clock rate for timeout calculation
941     */
942    rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);
943
944    return 1;
945};
946
Note: See TracBrowser for help on using the repository browser.