source: rtems/c/src/lib/libbsp/m68k/gen68302/network/network.c @ 888bc77

4.104.114.84.95
Last change on this file since 888bc77 was 888bc77, checked in by Joel Sherrill <joel.sherrill@…>, on Jul 25, 2004 at 2:24:01 PM

2004-07-25 Joel Sherrill <joel@…>

  • network/network.c: Add include of <sys/errno.h>.
  • Property mode set to 100644
File size: 21.2 KB
Line 
1/*
2 * RTEMS driver for M68360 SCC1 Ethernet
3 * W. Eric Norum
4 * Saskatchewan Accelerator Laboratory
5 * University of Saskatchewan
6 * Saskatoon, Saskatchewan, CANADA
7 * eric@skatter.usask.ca
8 *
9 *  $Id$
10 *
11 * Modify for Motorola 68en320 Ethernet Controller
12 * CXR S.A. France - 2000/09/14  - franckj@cxr.fr
13 */
14#include <bsp.h>
15#include <stdio.h>
16#include <rtems/error.h>
17#include <m302_int.h>
18#include <rtems/rtems_bsdnet.h>
19
20#include <sys/param.h>
21#include <sys/mbuf.h>
22#include <sys/socket.h>
23#include <sys/sockio.h>
24#include <sys/errno.h>
25
26#include <net/if.h>
27
28#include <netinet/in.h>
29#include <netinet/if_ether.h>
30#include <rtems/m68k/m68302.h>
31
32/*
33 * Number of SCCs supported by this driver
34 */
35#define NSCCDRIVER      1
36
37/*
38 * Default number of buffer descriptors set aside for this driver.
39 * The number of transmit buffer descriptors has to be quite large
40 * since a single frame often uses four or more buffer descriptors.
41 */
42#define RX_BUF_COUNT     64
43#define TX_BUF_COUNT     64
44
45/*
46 * RTEMS event used by interrupt handler to signal driver tasks.
47 * This must not be any of the events used by the network task synchronization.
48 */
49#define INTERRUPT_EVENT RTEMS_EVENT_1
50
51/*
52 * RTEMS event used to start transmit daemon.
53 * This must not be the same as INTERRUPT_EVENT.
54 */
55#define START_TRANSMIT_EVENT    RTEMS_EVENT_2
56
57/*
58 * Receive buffer size -- Allow for a full ethernet packet including CRC
59 */
60#define RBUF_SIZE       1520
61
62#if (MCLBYTES < RBUF_SIZE)
63# error "Driver must have MCLBYTES > RBUF_SIZE"
64#endif
65
66static  struct m68302_imp *             a_m68302_imp;
67
68#define M302_ETHER_IVECTOR              0x40
69
70/*
71 * Per-device data
72 */
73struct scc_softc {
74        struct arpcom           arpcom;
75        struct mbuf             **rxMbuf;
76        struct mbuf             **txMbuf;
77        int                     acceptBroadcast;
78        int                     rxBdCount;
79        int                     txBdCount;
80        int                     txBdHead;
81        int                     txBdTail;
82        int                     txBdActiveCount;
83
84        struct m68302_scc_bd    *rxBdBase;
85        struct m68302_scc_bd    *txBdBase;
86
87        rtems_id                rxDaemonTid;
88        rtems_id                txDaemonTid;
89
90        /*
91         * Statistics
92         */
93        unsigned long   rxInterrupts;
94        unsigned long   rxNotFirst;
95        unsigned long   rxNotLast;
96        unsigned long   rxGiant;
97        unsigned long   rxNonOctet;
98        unsigned long   rxRunt;
99        unsigned long   rxBadCRC;
100        unsigned long   rxOverrun;
101        unsigned long   rxCollision;
102
103        unsigned long   txInterrupts;
104        unsigned long   txDeferred;
105        unsigned long   txHeartbeat;
106        unsigned long   txLateCollision;
107        unsigned long   txRetryLimit;
108        unsigned long   txUnderrun;
109        unsigned long   txLostCarrier;
110        unsigned long   txRawWait;
111        unsigned long   txCoalesced;
112        unsigned long   txCoalesceFailed;
113        unsigned long   txRetry;
114};
115static struct scc_softc scc_softc[NSCCDRIVER];
116
117/*
118 *  interrupt handler
119 */
120static rtems_isr
121m302Enet_interrupt_handler (rtems_vector_number v)
122{
123
124        /*
125         * Frame received?
126         */
127        if (M68en302imp_intr_event & INTR_EVENT_BIT_RFINT) {
128                M68en302imp_intr_event = INTR_EVENT_BIT_RFINT;
129                M68en302imp_intr_mask &= ~INTR_MASK_BIT_RFIEN;
130                scc_softc[0].rxInterrupts++;
131                rtems_event_send (scc_softc[0].rxDaemonTid, INTERRUPT_EVENT);
132        }
133
134        /*
135         * Buffer transmitted    or transmitter error?
136         */
137        if ((M68en302imp_intr_event & INTR_EVENT_BIT_TFINT) ||
138                 ((M68en302imp_intr_event & INTR_EVENT_BIT_TXB))){
139                M68en302imp_intr_event = INTR_EVENT_BIT_TFINT | INTR_EVENT_BIT_TXB;
140                M68en302imp_intr_mask &= ~(INTR_MASK_BIT_TFIEN | INTR_MASK_BIT_TXIEN);
141                scc_softc[0].txInterrupts++;
142                rtems_event_send (scc_softc[0].txDaemonTid, INTERRUPT_EVENT);
143        }
144}
145
146/*
147 * Initialize the ethernet hardware
148 */
149static void
150m302Enet_initialize_hardware (struct scc_softc *sc)
151{
152        int i;
153        unsigned char *hwaddr;
154        rtems_status_code status;
155        rtems_isr_entry old_handler;
156        struct m68302_scc_bd    *a_bd;                  /* Buffer Descriptor pointer */
157        ushort *cam;
158#define LBK             0x0008
159#define DSQE    0x0010
160#define FDE             0x0020
161
162        /*
163         * standard loopback
164         */
165        M68302imp_port_data     (1) &= ~(LBK);
166        M68302imp_port_data     (1) |= (FDE);
167
168        M68en302imp_ecntrl=0x0001;
169        /*
170         * Set dma configuration status register EDMA
171         */
172        i = (sc->txBdCount == 16) ? EDMA_BDSIZE_16T_112R :
173                        (sc->txBdCount == 32) ? EDMA_BDSIZE_32T_96R :
174                        (sc->txBdCount == 64) ? EDMA_BDSIZE_64T_64R :
175                        EDMA_BDSIZE_8T_120R;
176
177        M68en302imp_edma =  EDMA_BLIM_8ACCESS | EDMA_WMRK_16FIFO | EDMA_BIT_TSRLY | (ushort)i;
178
179        /*
180         * Set maximum receive buffer length
181         */
182
183        M68en302imp_emrblr = RBUF_SIZE; /* 1520 */
184
185        /*
186         * Set interrupt vector
187         */
188        M68en302imp_intr_vect = M302_ETHER_IVECTOR;
189
190        M68en302imp_intr_mask=0x0;
191
192        /*
193         * Set ethernet Configuration
194         */
195        M68en302imp_ecnfig=0x0000;
196
197        /*
198         * Set ETHER_TEST
199         */
200        M68en302imp_ether_test=0x0000;
201
202        /*
203         *  Set AR control Register
204         *      Ignore/accept broadcast packets as specified
205         */
206        M68en302imp_ar_cntrl = ((sc->acceptBroadcast) ? 0 : AR_CNTRL_BIT_NO_BROADCAST) ;
207
208        /*
209         * Allocate mbuf pointers
210         */
211        sc->rxMbuf = malloc (sc->rxBdCount * sizeof *sc->rxMbuf, M_MBUF, M_NOWAIT);
212        sc->txMbuf = malloc (sc->txBdCount * sizeof *sc->txMbuf, M_MBUF, M_NOWAIT);
213        if (!sc->rxMbuf || !sc->txMbuf)
214                rtems_panic ("No memory for mbuf pointers");
215
216        /*
217         * Set our physical address
218         */
219        hwaddr = sc->arpcom.ac_enaddr;
220
221        cam=(ushort *)(M68en302imp_cet);
222        for (i=0;i<64;i++){
223                cam[(4*i)]=0x00ff;
224                cam[(4*i)+1]=0x00ff;
225                cam[(4*i)+2]=0x00ff;
226        }
227
228        cam[4] = (hwaddr[0] << 8) | hwaddr[1];
229        cam[5] = (hwaddr[2] << 8) | hwaddr[3];
230        cam[6] = (hwaddr[4] << 8) | hwaddr[5];
231
232        /*
233         * Set receiver and transmitter buffer descriptor bases
234         */
235        a_bd = M68302imp_a_eth_bd (0);                  /* point to first BD */
236
237        for (i=0;i<128;i++){
238
239                M68302_scc_bd_stat_ctrl (a_bd + i) = 0;
240                M68302_scc_bd_data_lgth (a_bd + i) = 0;
241                M68302_scc_bd_p_buffer  (a_bd + i) = NULL;
242        }
243
244        sc->txBdBase = M68302imp_a_eth_bd (  0 );                       /* point to first BD */
245        sc->rxBdBase = M68302imp_a_eth_bd ( sc->txBdCount);             /* point to first RX BD atfer all TX*/
246
247        /*
248         * Set up transmit buffer descriptors
249         */
250        for (i = 0 ; i < sc->txBdCount ; i++) {
251                sc->txMbuf[i] = NULL;
252        }
253        sc->txBdHead = sc->txBdTail = 0;
254        sc->txBdActiveCount = 0;
255
256        /*
257         * Clear any outstanding events
258         */
259        M68en302imp_intr_event = 0x07FF;
260        /*
261         * Set up interrupts
262         */
263
264        status = rtems_interrupt_catch (m302Enet_interrupt_handler,
265                                                M302_ETHER_IVECTOR,
266                                                &old_handler);
267        if (status != RTEMS_SUCCESSFUL)
268                rtems_panic ("Can't attach M302 ether interrupt handler: %s\r\n",
269                                                rtems_status_text (status));
270}
271
272/*
273 * Soak up buffer descriptors that have been sent
274 * Note that a buffer descriptor can't be retired as soon as it becomes
275 * ready.  The MC68360 Errata (May 96) says that, "If an Ethernet frame is
276 *  made up of multiple buffers, the user should not reuse the first buffer
277 * descriptor until the last buffer descriptor of the frame has had its
278 * ready bit cleared by the CPM".
279 */
280static void
281m302Enet_retire_tx_bd (struct scc_softc *sc)
282{
283
284        uint16_t         status;
285        int i;
286        int nRetired;
287        struct mbuf *m, *n;
288        int retries = 0;
289        int saveStatus = 0;
290
291        i = sc->txBdTail;
292        nRetired = 0;
293        while ((sc->txBdActiveCount != 0)
294           &&  (((status = (sc->txBdBase + i)->stat_ctrl) & BUF_STAT_READY) == 0)) {
295                /*
296                 * Check for errors which stop the transmitter.
297                 */
298                if (status & (BUF_STAT_LATE_COLLISION |
299                                BUF_STAT_RETRY_LIMIT |
300                                BUF_STAT_UNDERRUN)) {
301                        int j;
302
303                        if (status & BUF_STAT_LATE_COLLISION)
304                                sc->txLateCollision++;
305                        if (status & BUF_STAT_RETRY_LIMIT)
306                                sc->txRetryLimit++;
307                        if (status & BUF_STAT_UNDERRUN)
308                                sc->txUnderrun++;
309
310                        /*
311                         * Reenable buffer descriptors
312                         */
313                        j = sc->txBdTail;
314                        for (;;) {
315                                status = (sc->txBdBase + j)->stat_ctrl;
316                                if (status & BUF_STAT_READY)
317                                        break;
318                                (sc->txBdBase + j)->stat_ctrl = BUF_STAT_READY |
319                                        (status & ( BUF_STAT_WRAP |
320                                                   BUF_STAT_INTERRUPT |
321                                                   BUF_STAT_LAST |
322                                                   BUF_STAT_TX_CRC));
323                                if (status & BUF_STAT_LAST)
324                                        break;
325                                if (++j == sc->txBdCount)
326                                        j = 0;
327                        }
328
329                        /*
330                         * Move transmitter back to the first
331                         * buffer descriptor in the frame.
332                         */
333/*                      m360.scc1p._tbptr = m360.scc1p.tbase +
334                                sc->txBdTail * sizeof (m360BufferDescriptor_t);
335*/
336                        /*
337                         * Restart the transmitter
338                         */
339/*                      M360ExecuteRISC (M360_CR_OP_RESTART_TX | M360_CR_CHAN_SCC1);*/
340                        continue;
341                }
342                saveStatus |= status;
343                retries += (status >> 2) & 0xF;
344                nRetired++;
345                if (status & BUF_STAT_LAST) {
346                        /*
347                         * A full frame has been transmitted.
348                         * Free all the associated buffer descriptors.
349                         */
350                        if (saveStatus & BUF_STAT_DEFER)
351                                sc->txDeferred++;
352                        if (saveStatus & BUF_STAT_HEARTBIT)
353                                sc->txHeartbeat++;
354                        if (saveStatus & BUF_STAT_CARRIER_LOST)
355                                sc->txLostCarrier++;
356                        saveStatus = 0;
357                        sc->txRetry += retries;
358                        retries = 0;
359                        sc->txBdActiveCount -= nRetired;
360                        while (nRetired) {
361                                nRetired--;
362                                m = sc->txMbuf[sc->txBdTail];
363                                MFREE (m, n);
364                                if (++sc->txBdTail == sc->txBdCount)
365                                        sc->txBdTail = 0;
366                        }
367                }
368                if (++i == sc->txBdCount)
369                        i = 0;
370        }
371
372}
373
374/*
375 * SCC reader task
376 */
377static void
378scc_rxDaemon (void *arg)
379{
380
381        struct scc_softc *sc = (struct scc_softc *)arg;
382        struct ifnet *ifp = &sc->arpcom.ac_if;
383        struct mbuf *m;
384        uint16_t         status;
385        volatile struct m68302_scc_bd *rxBd;
386        int rxBdIndex;
387
388        /*
389         * Allocate space for incoming packets and start reception
390         */
391        for (rxBdIndex = 0 ; ;) {
392                rxBd = sc->rxBdBase + rxBdIndex;
393                MGETHDR (m, M_WAIT, MT_DATA);
394                MCLGET (m, M_WAIT);
395                m->m_pkthdr.rcvif = ifp;
396                sc->rxMbuf[rxBdIndex] = m;
397                rxBd->p_buffer = mtod (m, void *);
398
399                if (++rxBdIndex == sc->rxBdCount) {
400                        rxBd->stat_ctrl = BUF_STAT_EMPTY | BUF_STAT_INTERRUPT | BUF_STAT_WRAP;
401                        break;
402                }
403                rxBd->stat_ctrl = BUF_STAT_EMPTY | BUF_STAT_INTERRUPT;
404        }
405
406        /*
407         * Input packet handling loop
408         */
409        rxBdIndex = 0;
410        for (;;) {
411                rxBd = sc->rxBdBase + rxBdIndex;
412
413                /*
414                 * Wait for packet if there's not one ready
415                 */
416                if ((status = rxBd->stat_ctrl) & BUF_STAT_EMPTY) {
417                        /*
418                         * Clear old events
419                         */
420                        M68en302imp_intr_event = INTR_EVENT_BIT_RFINT;
421
422                        /*
423                         * Wait for packet
424                         * Note that the buffer descriptor is checked
425                         * *before* the event wait -- this catches the
426                         * possibility that a packet arrived between the
427                         * `if' above, and the clearing of the event register.
428                         */
429                        while ((status = rxBd->stat_ctrl) & BUF_STAT_EMPTY) {
430                                rtems_interrupt_level level;
431                                rtems_event_set events;
432
433                                /*
434                                 * Unmask RXF (Full frame received) event
435                                 */
436                                rtems_interrupt_disable (level);
437                                M68en302imp_intr_mask |= INTR_MASK_BIT_RFIEN;
438
439                                rtems_interrupt_enable (level);
440                                rtems_bsdnet_event_receive (INTERRUPT_EVENT,
441                                                RTEMS_WAIT|RTEMS_EVENT_ANY,
442                                                RTEMS_NO_TIMEOUT,
443                                                &events);
444                        }
445                }
446
447                /*
448                 * Check that packet is valid
449                 */
450                if ((status & (BUF_STAT_LAST |
451                                BUF_STAT_FIRST_IN_FRAME |
452                                BUF_STAT_LONG |
453                                BUF_STAT_NONALIGNED |
454                                BUF_STAT_SHORT |
455                                BUF_STAT_CRC_ERROR |
456                                BUF_STAT_OVERRUN |
457                                BUF_STAT_COLLISION)) ==
458                                                (BUF_STAT_LAST |
459                                                BUF_STAT_FIRST_IN_FRAME)) {
460                        /*
461                         * Pass the packet up the chain.
462                         * FIXME: Packet filtering hook could be done here.
463                         */
464                        struct ether_header *eh;
465
466                        m = sc->rxMbuf[rxBdIndex];
467                        m->m_len = m->m_pkthdr.len = rxBd->data_lgth -
468                                                sizeof(uint32_t) -
469                                                sizeof(struct ether_header);
470                        eh = mtod (m, struct ether_header *);
471                        m->m_data += sizeof(struct ether_header);
472
473                        ether_input (ifp, eh, m);
474
475                        /*
476                         * Allocate a new mbuf
477                         */
478                        MGETHDR (m, M_WAIT, MT_DATA);
479                        MCLGET (m, M_WAIT);
480                        m->m_pkthdr.rcvif = ifp;
481                        sc->rxMbuf[rxBdIndex] = m;
482                        rxBd->p_buffer = mtod (m, void *);
483                }
484                else {
485                        /*
486                         * Something went wrong with the reception
487                         */
488                        if (!(status & BUF_STAT_LAST))
489                                sc->rxNotLast++;
490                        if (!(status & BUF_STAT_FIRST_IN_FRAME))
491                                sc->rxNotFirst++;
492                        if (status & BUF_STAT_LONG)
493                                sc->rxGiant++;
494                        if (status & BUF_STAT_NONALIGNED)
495                                sc->rxNonOctet++;
496                        if (status & BUF_STAT_SHORT)
497                                sc->rxRunt++;
498                        if (status & BUF_STAT_CRC_ERROR)
499                                sc->rxBadCRC++;
500                        if (status & BUF_STAT_OVERRUN)
501                                sc->rxOverrun++;
502                        if (status & BUF_STAT_COLLISION)
503                                sc->rxCollision++;
504                }
505
506                /*
507                 * Reenable the buffer descriptor
508                 */
509                rxBd->stat_ctrl = (status & (BUF_STAT_WRAP | BUF_STAT_INTERRUPT)) | BUF_STAT_EMPTY;
510
511                /*
512                 * Move to next buffer descriptor
513                 */
514                if (++rxBdIndex == sc->rxBdCount)
515                        rxBdIndex = 0;
516        }
517
518}
519
520static void
521sendpacket (struct ifnet *ifp, struct mbuf *m)
522{
523
524        struct scc_softc *sc = ifp->if_softc;
525        volatile struct m68302_scc_bd *firstTxBd, *txBd;
526        struct mbuf *l = NULL;
527        uint16_t         status;
528        int nAdded;
529
530        /*
531         * Free up buffer descriptors
532         */
533        m302Enet_retire_tx_bd (sc);
534        /*
535         * Set up the transmit buffer descriptors.
536         * No need to pad out short packets since the
537         * hardware takes care of that automatically.
538         * No need to copy the packet to a contiguous buffer
539         * since the hardware is capable of scatter/gather DMA.
540         */
541        status = 0;
542        nAdded = 0;
543        txBd = firstTxBd = sc->txBdBase + sc->txBdHead;
544        while (m) {
545                /*
546                 * There are more mbufs in the packet than there
547                 * are transmit buffer descriptors.
548                 * Coalesce into a single buffer.
549                 */
550                if (nAdded == sc->txBdCount) {
551                        struct mbuf *nm;
552                        int j;
553                        char *dest;
554
555                        /*
556                         * Get the pointer to the first mbuf of the packet
557                         */
558                        if (sc->txBdTail != sc->txBdHead)
559                                rtems_panic ("sendpacket coalesce");
560                        m = sc->txMbuf[sc->txBdTail];
561
562                        /*
563                         * Rescind the buffer descriptor READY bits
564                         */
565                        for (j = 0 ; j < sc->txBdCount ; j++)
566                                (sc->txBdBase + j)->stat_ctrl = 0;
567
568                        /*
569                         * Allocate an mbuf cluster
570                         * Toss the packet if allocation fails
571                         */
572                        MGETHDR (nm, M_DONTWAIT, MT_DATA);
573                        if (nm == NULL) {
574                                sc->txCoalesceFailed++;
575                                m_freem (m);
576
577                                return;
578                        }
579                        MCLGET (nm, M_DONTWAIT);
580                        if (nm->m_ext.ext_buf == NULL) {
581                                sc->txCoalesceFailed++;
582                                m_freem (m);
583                                m_free (nm);
584
585                                return;
586                        }
587                        nm->m_pkthdr = m->m_pkthdr;
588                        nm->m_len = nm->m_pkthdr.len;
589
590                        /*
591                         * Copy data from packet chain to mbuf cluster
592                         */
593                        sc->txCoalesced++;
594                        dest = nm->m_ext.ext_buf;
595                        while (m) {
596                                struct mbuf *n;
597
598                                if (m->m_len) {
599                                        memcpy (dest, mtod(m, caddr_t), m->m_len);
600                                        dest += m->m_len;
601                                }
602                                MFREE (m, n);
603                                m = n;
604                        }
605
606                        /*
607                         * Redo the send with the new mbuf cluster
608                         */
609                        m = nm;
610                        nAdded = 0;
611                        status = 0;
612
613                        continue;
614                }
615
616                /*
617                 * Wait for buffer descriptor to become available.
618                 */
619                if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
620                        /*
621                         * Clear old events
622                         */
623                        M68en302imp_intr_event = INTR_EVENT_BIT_TFINT | INTR_EVENT_BIT_TXB;
624
625                        /*
626                         * Wait for buffer descriptor to become available.
627                         * Note that the buffer descriptors are checked
628                         * *before* entering the wait loop -- this catches
629                         * the possibility that a buffer descriptor became
630                         * available between the `if' above, and the clearing
631                         * of the event register.
632                         * This is to catch the case where the transmitter
633                         * stops in the middle of a frame -- and only the
634                         * last buffer descriptor in a frame can generate
635                         * an interrupt.
636                         */
637                        m302Enet_retire_tx_bd (sc);
638                        while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
639                                rtems_interrupt_level level;
640                                rtems_event_set events;
641
642                                /*
643                                 * Unmask TXB (buffer transmitted) and
644                                 * TXE (transmitter error) events.
645                                 */
646                                rtems_interrupt_disable (level);
647                                M68en302imp_intr_mask |= INTR_MASK_BIT_TFIEN | INTR_MASK_BIT_TXIEN;
648                                rtems_interrupt_enable (level);
649
650                                rtems_bsdnet_event_receive (INTERRUPT_EVENT,
651                                                RTEMS_WAIT|RTEMS_EVENT_ANY,
652                                                RTEMS_NO_TIMEOUT,
653                                                &events);
654                                m302Enet_retire_tx_bd (sc);
655                        }
656                }
657
658                /*
659                 * The IP fragmentation routine in ip_output
660                 * can produce packet fragments with zero length.
661                 */
662                if (m->m_len) {
663                        /*
664                         * Fill in the buffer descriptor.
665                         * Don't set the READY flag in the first buffer
666                         * descriptor till the whole packet has been readied.
667                         */
668                        txBd = sc->txBdBase + sc->txBdHead;
669                        txBd->p_buffer = mtod (m, void *);
670                        txBd->data_lgth = m->m_len;
671
672                        sc->txMbuf[sc->txBdHead] = m;
673                        status = nAdded ? BUF_STAT_READY : 0;
674                        if (++sc->txBdHead == sc->txBdCount) {
675                                status |= BUF_STAT_WRAP;
676                                sc->txBdHead = 0;
677                        }
678                        txBd->stat_ctrl = status;
679                        l = m;
680                        m = m->m_next;
681                        nAdded++;
682
683                }
684                else {
685                        /*
686                         * Just toss empty mbufs
687                         */
688                        struct mbuf *n;
689                        MFREE (m, n);
690                        m = n;
691                        if (l != NULL)
692                                l->m_next = m;
693
694                }
695        }
696        if (nAdded) {
697                /*
698                 * Send the packet
699                 */
700                txBd->stat_ctrl = status | BUF_STAT_LAST | BUF_STAT_TX_CRC | BUF_STAT_INTERRUPT;
701                firstTxBd->stat_ctrl |= BUF_STAT_READY;
702                sc->txBdActiveCount += nAdded;
703
704        }
705
706}
707
708/*
709 * Driver transmit daemon
710 */
711void
712scc_txDaemon (void *arg)
713{
714
715        struct scc_softc *sc = (struct scc_softc *)arg;
716        struct ifnet *ifp = &sc->arpcom.ac_if;
717        struct mbuf *m;
718        rtems_event_set events;
719
720        for (;;) {
721                /*
722                 * Wait for packet
723                 */
724                rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events);
725
726                /*
727                 * Send packets till queue is empty
728                 */
729                for (;;) {
730                        /*
731                         * Get the next mbuf chain to transmit.
732                         */
733                        IF_DEQUEUE(&ifp->if_snd, m);
734                        if (!m)
735                                break;
736                        sendpacket (ifp, m);
737                }
738                ifp->if_flags &= ~IFF_OACTIVE;
739        }
740
741}
742
743/*
744 * Send packet (caller provides header).
745 */
746static void
747scc_start (struct ifnet *ifp)
748{
749        struct scc_softc *sc = ifp->if_softc;
750
751        rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
752        ifp->if_flags |= IFF_OACTIVE;
753}
754
755/*
756 * Initialize and start the device
757 */
758static void
759scc_init (void *arg)
760{
761        struct scc_softc *sc = arg;
762        struct ifnet *ifp = &sc->arpcom.ac_if;
763
764        if (sc->txDaemonTid == 0) {
765
766                /*
767                 * Set up SCC hardware
768                 */
769                m302Enet_initialize_hardware (sc);
770
771                sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, scc_txDaemon, sc);
772                sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, scc_rxDaemon, sc);
773
774        }
775
776        /*
777         * Set flags appropriately
778         */
779/*      if (ifp->if_flags & IFF_PROMISC)
780                m360.scc1.psmr |= 0x200;
781        else
782                m360.scc1.psmr &= ~0x200;
783*/
784        /*
785         * Tell the world that we're running.
786         */
787        ifp->if_flags |= IFF_RUNNING;
788
789        /*
790         * Enable receiver and transmitter
791         */
792        M68en302imp_ecntrl = ECNTRL_BIT_RESET   | ECNTRL_BIT_ETHER_EN;
793
794}
795
796/*
797 * Stop the device
798 */
799static void
800scc_stop (struct scc_softc *sc)
801{
802
803        struct ifnet *ifp = &sc->arpcom.ac_if;
804
805        ifp->if_flags &= ~IFF_RUNNING;
806
807        /*
808         * Shut down receiver and transmitter
809         */
810        M68en302imp_ecntrl &= ~(ECNTRL_BIT_RESET        | ECNTRL_BIT_ETHER_EN);
811
812}
813
814/*
815 * Show interface statistics
816 */
817static void
818scc_stats (struct scc_softc *sc)
819{
820        printf ("      Rx Interrupts:%-8lu", sc->rxInterrupts);
821        printf ("       Not First:%-8lu", sc->rxNotFirst);
822        printf ("        Not Last:%-8lu\r\n", sc->rxNotLast);
823        printf ("              Giant:%-8lu", sc->rxGiant);
824        printf ("            Runt:%-8lu", sc->rxRunt);
825        printf ("       Non-octet:%-8lu\r\n", sc->rxNonOctet);
826        printf ("            Bad CRC:%-8lu", sc->rxBadCRC);
827        printf ("         Overrun:%-8lu", sc->rxOverrun);
828        printf ("       Collision:%-8lu\r\n", sc->rxCollision);
829/*      printf ("          Discarded:%-8lu\r\n", (unsigned long)m360.scc1p.un.ethernet.disfc);
830*/
831        printf ("      Tx Interrupts:%-8lu", sc->txInterrupts);
832        printf ("        Deferred:%-8lu", sc->txDeferred);
833        printf (" Missed Hearbeat:%-8lu\r\n", sc->txHeartbeat);
834        printf ("         No Carrier:%-8lu", sc->txLostCarrier);
835        printf ("Retransmit Limit:%-8lu", sc->txRetryLimit);
836        printf ("  Late Collision:%-8lu\r\n", sc->txLateCollision);
837        printf ("           Underrun:%-8lu", sc->txUnderrun);
838        printf (" Raw output wait:%-8lu", sc->txRawWait);
839        printf ("       Coalesced:%-8lu\r\n", sc->txCoalesced);
840        printf ("    Coalesce failed:%-8lu", sc->txCoalesceFailed);
841        printf ("         Retries:%-8lu\r\n", sc->txRetry);
842}
843
844/*
845 * Driver ioctl handler
846 */
847static int
848scc_ioctl (struct ifnet *ifp, int command, caddr_t data)
849{
850
851        struct scc_softc *sc = ifp->if_softc;
852        int error = 0;
853
854        switch (command) {
855        case SIOCGIFADDR:
856        case SIOCSIFADDR:
857                ether_ioctl (ifp, command, data);
858                break;
859
860        case SIOCSIFFLAGS:
861                switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
862                case IFF_RUNNING:
863                        scc_stop (sc);
864                        break;
865
866                case IFF_UP:
867                        scc_init (sc);
868                        break;
869
870                case IFF_UP | IFF_RUNNING:
871                        scc_stop (sc);
872                        scc_init (sc);
873                        break;
874
875                default:
876                        break;
877                }
878                break;
879
880        case SIO_RTEMS_SHOW_STATS:
881                scc_stats (sc);
882                break;
883
884        /*
885         * FIXME: All sorts of multicast commands need to be added here!
886         */
887        default:
888                error = EINVAL;
889                break;
890        }
891        return error;
892
893}
894
895/*
896 * Attach an SCC driver to the system
897 */
898int
899rtems_ether1_driver_attach (struct rtems_bsdnet_ifconfig *config)
900{
901        struct scc_softc *sc;
902        struct ifnet *ifp;
903        int mtu;
904        int unitNumber;
905        char *unitName;
906
907        a_m68302_imp = (struct m68302_imp *)0x700000L;
908        /*
909         * Parse driver name
910         */
911        if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0)
912                return 0;
913
914        /*
915         * Is driver free?
916         */
917        if ((unitNumber <= 0) || (unitNumber > NSCCDRIVER)) {
918                printf ("Bad SCC unit number.\r\n");
919                return 0;
920        }
921        sc = &scc_softc[unitNumber - 1];
922        ifp = &sc->arpcom.ac_if;
923        if (ifp->if_softc != NULL) {
924                printf ("Driver already in use.\r\n");
925                return 0;
926        }
927
928        /*
929         * Process options
930         */
931        if (config->hardware_address) {
932                memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
933        }
934
935        if (config->mtu)
936                mtu = config->mtu;
937        else
938                mtu = ETHERMTU;
939        if (config->rbuf_count)
940                sc->rxBdCount = config->rbuf_count;
941        else
942                sc->rxBdCount = RX_BUF_COUNT;
943        if (config->xbuf_count)
944                sc->txBdCount = config->xbuf_count;
945        else
946                sc->txBdCount = TX_BUF_COUNT;
947        sc->acceptBroadcast = !config->ignore_broadcast;
948
949        /*
950         * Set up network interface values
951         */
952        ifp->if_softc = sc;
953        ifp->if_unit = unitNumber;
954        ifp->if_name = unitName;
955        ifp->if_mtu = mtu;
956        ifp->if_init = scc_init;
957        ifp->if_ioctl = scc_ioctl;
958        ifp->if_start = scc_start;
959        ifp->if_output = ether_output;
960        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
961        if (ifp->if_snd.ifq_maxlen == 0)
962                ifp->if_snd.ifq_maxlen = ifqmaxlen;
963
964        /*
965         * Attach the interface
966         */
967        if_attach (ifp);
968        ether_ifattach (ifp);
969        return 1;
970};
Note: See TracBrowser for help on using the repository browser.