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

4.104.114.84.95
Last change on this file since da8d470 was da8d470, checked in by Joel Sherrill <joel.sherrill@…>, on Dec 14, 2000 at 7:38:51 PM

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

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