source: rtems/c/src/lib/libbsp/m68k/gen68302/network/network.c @ 8c4c223

4.104.114.84.95
Last change on this file since 8c4c223 was 8b868a11, checked in by Joel Sherrill <joel.sherrill@…>, on 12/14/00 at 17:53:53

2000-12-11 Joel Sherrill <joel@…>

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