source: rtems/c/src/lib/libbsp/powerpc/eth_comm/network/network.c @ 8ef3818

4.104.114.84.95
Last change on this file since 8ef3818 was 8ef3818, checked in by Joel Sherrill <joel.sherrill@…>, on 06/12/00 at 19:57:02

Patch from John Cotton <john.cotton@…>, Charles-Antoine Gauthier
<charles.gauthier@…>, and Darlene A. Stewart
<Darlene.Stewart@…> to add support for a number of very
significant things:

+ BSPs for many variations on the Motorola MBX8xx board series
+ Cache Manager including initial support for m68040

and PowerPC

+ Rework of mpc8xx libcpu code so all mpc8xx CPUs now use

same code base.

+ Rework of eth_comm BSP to utiltize above.

John reports this works on the 821 and 860

  • Property mode set to 100644
File size: 39.2 KB
Line 
1/*
2 * RTEMS/TCPIP driver for MPC860 SCC1 Ethernet
3 *
4 * Modified for MPC860 by Jay Monkman (jmonkman@frasca.com)
5 *
6 * This supports ethernet on either SCC1 or the FEC of the MPC860T.
7 *  Right now, we only do 10 Mbps, even with the FEC. The function
8 *  rtems_m860_enet_driver_attach determines which one to use. Currently,
9 *  only one may be used at a time.
10 *
11 * W. Eric Norum
12 * Saskatchewan Accelerator Laboratory
13 * University of Saskatchewan
14 * Saskatoon, Saskatchewan, CANADA
15 * eric@skatter.usask.ca
16 *
17 *  $Id$
18 */
19#include <bsp.h>
20#include <stdio.h>
21#include <rtems/error.h>
22#include <rtems/rtems_bsdnet.h>
23
24#include <sys/param.h>
25#include <sys/mbuf.h>
26#include <sys/socket.h>
27#include <sys/sockio.h>
28
29#include <net/if.h>
30
31#include <netinet/in.h>
32#include <netinet/if_ether.h>
33
34/*
35 * Number of interfaces supported by this driver
36 */
37#define NIFACES 1
38
39/*
40 * Default number of buffer descriptors set aside for this driver.
41 * The number of transmit buffer descriptors has to be quite large
42 * since a single frame often uses four or more buffer descriptors.
43 */
44#define RX_BUF_COUNT     32
45#define TX_BUF_COUNT     8
46#define TX_BD_PER_BUF    4
47
48/*
49 * RTEMS event used by interrupt handler to signal daemons.
50 * This must *not* be the same event used by the TCP/IP task synchronization.
51 */
52#define INTERRUPT_EVENT RTEMS_EVENT_1
53
54/*
55 * RTEMS event used to start transmit daemon.
56 * This must not be the same as INTERRUPT_EVENT.
57 */
58#define START_TRANSMIT_EVENT    RTEMS_EVENT_2
59
60/*
61 * Receive buffer size -- Allow for a full ethernet packet plus a pointer
62 */
63#define RBUF_SIZE       1520
64
65#if (MCLBYTES < RBUF_SIZE)
66# error "Driver must have MCLBYTES > RBUF_SIZE"
67#endif
68
69/*
70 * Per-device data
71 */
72struct m860_enet_struct {
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        m8xxBufferDescriptor_t  *rxBdBase;
83        m8xxBufferDescriptor_t  *txBdBase;
84        rtems_id                rxDaemonTid;
85        rtems_id                txDaemonTid;
86
87        /*
88         * Statistics
89         */
90        unsigned long   rxInterrupts;
91        unsigned long   rxNotFirst;
92        unsigned long   rxNotLast;
93        unsigned long   rxGiant;
94        unsigned long   rxNonOctet;
95        unsigned long   rxRunt;
96        unsigned long   rxBadCRC;
97        unsigned long   rxOverrun;
98        unsigned long   rxCollision;
99
100        unsigned long   txInterrupts;
101        unsigned long   txDeferred;
102        unsigned long   txHeartbeat;
103        unsigned long   txLateCollision;
104        unsigned long   txRetryLimit;
105        unsigned long   txUnderrun;
106        unsigned long   txLostCarrier;
107        unsigned long   txRawWait;
108};
109static struct m860_enet_struct enet_driver[NIFACES];
110
111/*
112 * SCC1 interrupt handler
113 */
114static rtems_isr
115m860_scc1_interrupt_handler (rtems_vector_number v)
116{
117        /*
118         * Frame received?
119         */
120        if ((m8xx.scc1.sccm & 0x8) && (m8xx.scc1.scce & 0x8)) {
121                m8xx.scc1.scce = 0x8;
122                /* I don't think the next line is needed. It was in
123                 * the 68360 stuff, though.
124                 *   m8xx.scc1.sccm &= ~0x8;
125                 */
126                enet_driver[0].rxInterrupts++;
127                rtems_event_send (enet_driver[0].rxDaemonTid, INTERRUPT_EVENT);
128        }
129
130        /*
131         * Buffer transmitted or transmitter error?
132         */
133        if ((m8xx.scc1.sccm & 0x12) && (m8xx.scc1.scce & 0x12)) {
134                m8xx.scc1.scce = 0x12;
135                /* I don't think the next line is needed. It was in
136                 * the 68360 stuff, though.
137                 *   m8xx.scc1.sccm &= ~0x12;
138                 */
139                enet_driver[0].txInterrupts++;
140                rtems_event_send (enet_driver[0].txDaemonTid, INTERRUPT_EVENT);
141        }
142        m8xx.cisr = 1UL << 30;  /* Clear SCC1 interrupt-in-service bit */
143}
144
145/*
146 * FEC interrupt handler
147 */
148static rtems_isr
149m860_fec_interrupt_handler (rtems_vector_number v)
150{
151  /*
152   * Frame received?
153   */
154  if (m8xx.fec.ievent & M8xx_FEC_IEVENT_RFINT) {
155    m8xx.fec.ievent = M8xx_FEC_IEVENT_RFINT;
156    enet_driver[0].rxInterrupts++;
157    rtems_event_send (enet_driver[0].rxDaemonTid, INTERRUPT_EVENT);
158  }
159 
160  /*
161   * Buffer transmitted or transmitter error?
162   */
163  if (m8xx.fec.ievent & M8xx_FEC_IEVENT_TFINT) {
164    m8xx.fec.ievent = M8xx_FEC_IEVENT_TFINT;
165    enet_driver[0].txInterrupts++;
166    rtems_event_send (enet_driver[0].txDaemonTid, INTERRUPT_EVENT);
167  }
168}
169
170/*
171 * Initialize the ethernet hardware
172 */
173static void
174m860_scc_initialize_hardware (struct m860_enet_struct *sc)
175{
176  int i;
177  unsigned char *hwaddr;
178  rtems_status_code status;
179  rtems_isr_entry old_handler;
180 
181  /*
182   * Configure port A CLK1, CLK2, TXD1 and RXD1 pins
183   */
184  m8xx.papar |=  0x303;
185  m8xx.padir &= ~0x303;
186  m8xx.paodr &= ~0x303;
187 
188  /*
189   * Configure port C CTS1* and CD1* pins, and PC4-PC7
190   * 
191   */
192  m8xx.pcpar &= ~0x30;
193  m8xx.pcdir |= 0x0f00;
194  m8xx.pcdir &= ~0x30;
195  m8xx.pcso  |=  0x30;
196  m8xx.pcdat &= ~0x0f00;  /* Clear LOOP */
197  m8xx.pcdat |= 0x0700;   /* Set FULDL, TPSQEL, TPAPCE */
198 
199  /*
200   * Connect CLK1 and CLK2 to SCC1
201   */
202  m8xx.sicr &= ~0xFF;
203  m8xx.sicr |= (5 << 3) | 4;
204 
205  /*
206   * Initialize SDMA configuration register
207   */
208  m8xx.sdcr = 1;
209 
210  /*
211   * Allocate mbuf pointers
212   */
213  sc->rxMbuf = malloc (sc->rxBdCount * sizeof *sc->rxMbuf,
214                       M_MBUF, M_NOWAIT);
215  sc->txMbuf = malloc (sc->txBdCount * sizeof *sc->txMbuf,
216                       M_MBUF, M_NOWAIT);
217  if (!sc->rxMbuf || !sc->txMbuf)
218    rtems_panic ("No memory for mbuf pointers");
219 
220  /*
221   * Set receiver and transmitter buffer descriptor bases
222   */
223  sc->rxBdBase = m8xx_bd_allocate(sc->rxBdCount);
224  sc->txBdBase = m8xx_bd_allocate(sc->txBdCount);
225  m8xx.scc1p.rbase = (char *)sc->rxBdBase - (char *)&m8xx;
226  m8xx.scc1p.tbase = (char *)sc->txBdBase - (char *)&m8xx;
227 
228  /*
229   * Send "Init parameters" command
230   */
231  m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SCC1);
232 
233  /*
234   * Set receive and transmit function codes
235   */
236  m8xx.scc1p.rfcr = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0);
237  m8xx.scc1p.tfcr = M8xx_TFCR_MOT | M8xx_TFCR_DMA_SPACE(0);
238 
239  /*
240   * Set maximum receive buffer length
241   */
242  m8xx.scc1p.mrblr = RBUF_SIZE;
243 
244  /*
245   * Set CRC parameters
246   */
247  m8xx.scc1p.un.ethernet.c_pres = 0xFFFFFFFF;
248  m8xx.scc1p.un.ethernet.c_mask = 0xDEBB20E3;
249 
250  /*
251   * Clear diagnostic counters
252   */
253  m8xx.scc1p.un.ethernet.crcec = 0;
254  m8xx.scc1p.un.ethernet.alec = 0;
255  m8xx.scc1p.un.ethernet.disfc = 0;
256 
257  /*
258   * Set pad value
259   */
260  m8xx.scc1p.un.ethernet.pads = 0x8888;
261 
262  /*
263   * Set retry limit
264   */
265  m8xx.scc1p.un.ethernet.ret_lim = 15;
266 
267  /*
268   * Set maximum and minimum frame length
269   */
270  m8xx.scc1p.un.ethernet.mflr = 1518;
271  m8xx.scc1p.un.ethernet.minflr = 64;
272  m8xx.scc1p.un.ethernet.maxd1 = RBUF_SIZE;
273  m8xx.scc1p.un.ethernet.maxd2 = RBUF_SIZE;
274 
275  /*
276   * Clear group address hash table
277   */
278  m8xx.scc1p.un.ethernet.gaddr1 = 0;
279  m8xx.scc1p.un.ethernet.gaddr2 = 0;
280  m8xx.scc1p.un.ethernet.gaddr3 = 0;
281  m8xx.scc1p.un.ethernet.gaddr4 = 0;
282 
283  /*
284   * Set our physical address
285   */
286  hwaddr = sc->arpcom.ac_enaddr;
287 
288  m8xx.scc1p.un.ethernet.paddr_h = (hwaddr[5] << 8) | hwaddr[4];
289  m8xx.scc1p.un.ethernet.paddr_m = (hwaddr[3] << 8) | hwaddr[2];
290  m8xx.scc1p.un.ethernet.paddr_l = (hwaddr[1] << 8) | hwaddr[0];
291 
292  /*
293   * Aggressive retry
294   */
295  m8xx.scc1p.un.ethernet.p_per = 0;
296 
297  /*
298   * Clear individual address hash table
299   */
300  m8xx.scc1p.un.ethernet.iaddr1 = 0;
301  m8xx.scc1p.un.ethernet.iaddr2 = 0;
302  m8xx.scc1p.un.ethernet.iaddr3 = 0;
303  m8xx.scc1p.un.ethernet.iaddr4 = 0;
304 
305  /*
306   * Clear temp address
307   */
308  m8xx.scc1p.un.ethernet.taddr_l = 0;
309  m8xx.scc1p.un.ethernet.taddr_m = 0;
310  m8xx.scc1p.un.ethernet.taddr_h = 0;
311 
312  /*
313   * Set up receive buffer descriptors
314   */
315  for (i = 0 ; i < sc->rxBdCount ; i++) {
316    (sc->rxBdBase + i)->status = 0;
317  }
318
319  /*
320   * Set up transmit buffer descriptors
321   */
322  for (i = 0 ; i < sc->txBdCount ; i++) {
323    (sc->txBdBase + i)->status = 0;
324    sc->txMbuf[i] = NULL;
325  }
326  sc->txBdHead = sc->txBdTail = 0;
327  sc->txBdActiveCount = 0;
328 
329  /*
330   * Clear any outstanding events
331   */
332  m8xx.scc1.scce = 0xFFFF;
333 
334  /*
335   * Set up interrupts
336   */
337  status = rtems_interrupt_catch (m860_scc1_interrupt_handler,
338                                  PPC_IRQ_CPM_SCC1,
339                                  &old_handler);
340  if (status != RTEMS_SUCCESSFUL) {
341    rtems_panic ("Can't attach M860 SCC1 interrupt handler: %s\n",
342                 rtems_status_text (status));
343  }
344  m8xx.scc1.sccm = 0;     /* No interrupts unmasked till necessary */
345  m8xx.cimr |= (1UL << 30);       /* Enable SCC1 interrupt */
346 
347  /*
348   * Set up General SCC Mode Register
349   * Ethernet configuration
350   */
351  m8xx.scc1.gsmr_h = 0x0;
352  m8xx.scc1.gsmr_l = 0x1088000c;
353 
354  /*
355   * Set up data synchronization register
356   * Ethernet synchronization pattern
357   */
358  m8xx.scc1.dsr = 0xd555;
359 
360  /*
361   * Set up protocol-specific mode register
362   *      No Heartbeat check
363   *      No force collision
364   *      Discard short frames
365   *      Individual address mode
366   *      Ethernet CRC
367   *      Not promisuous
368   *      Ignore/accept broadcast packets as specified
369   *      Normal backoff timer
370   *      No loopback
371   *      No input sample at end of frame
372   *      64-byte limit for late collision
373   *      Wait 22 bits before looking for start of frame delimiter
374   *      Disable full-duplex operation
375   */
376  m8xx.scc1.psmr = 0x080A | (sc->acceptBroadcast ? 0 : 0x100);
377 
378  /*
379   * Enable the TENA (RTS1*) pin
380   */
381  m8xx.pcpar |=  0x1;
382  m8xx.pcdir &= ~0x1;
383 
384 
385  /*
386   * Set up interrupts
387   * FIXME: DANGER: WARNING:
388   * CICR and SIMASK must be set in any module that uses
389   *   the CPM. Currently those are console-generic.c and
390   *   network.c. If the registers are not set the same
391   *   in both places, strange things may happen.
392   *   If they are only set in one place, then an application
393   *   that used the other module won't work correctly.
394   *   Put this comment in each module that sets these 2 registers
395   */
396  m8xx.cicr = 0x00e43e80;   /* SCaP=SCC1, SCbP=SCC2, SCcP=SCC3,
397                               SCdP=SCC4, IRL=1, HP=SCC1, IEN=1 */
398  m8xx.simask |= M8xx_SIMASK_LVM1;
399 
400  /*
401   * Enable receiver and transmitter
402   */
403  m8xx.scc1.gsmr_l = 0x1088003c;
404}
405
406static void
407m860_fec_initialize_hardware (struct m860_enet_struct *sc)
408{
409  int i;
410  unsigned char *hwaddr;
411  rtems_status_code status;
412  rtems_isr_entry old_handler;
413
414  /*
415   * Issue reset to FEC
416   */
417  m8xx.fec.ecntrl=0x1;
418
419  /*
420   * Put ethernet transciever in reset
421   */
422  m8xx.pgcra |= 0x80;
423
424  /*
425   * Configure I/O ports
426   */
427  m8xx.pdpar = 0x1fff;
428  m8xx.pddir = 0x1c58;
429
430  /*
431   * Take ethernet transciever out of reset
432   */
433  m8xx.pgcra &= ~0x80;
434
435
436  /*
437   * Set SIU interrupt level to LVL2
438   * 
439   */
440  m8xx.fec.ivec = 0x02 << 29;
441 
442  /*
443   * Set the TX and RX fifo sizes. For now, we'll split it evenly
444   */
445  /* If you uncomment these, the FEC will not work right.
446  m8xx.fec.r_fstart = ((m8xx.fec.r_bound & 0x3ff) >> 2) & 0x3ff;
447  m8xx.fec.x_fstart = 0;
448  */
449
450  /*
451   * Set our physical address
452   */
453  hwaddr = sc->arpcom.ac_enaddr;
454 
455  m8xx.fec.addr_low = (hwaddr[0] << 24) | (hwaddr[1] << 16) |
456                      (hwaddr[2] << 8)  | (hwaddr[3] << 0);
457  m8xx.fec.addr_high = (hwaddr[4] << 24) | (hwaddr[5] << 16);
458
459  /*
460   * Clear the hash table
461   */
462  m8xx.fec.hash_table_high = 0;
463  m8xx.fec.hash_table_low  = 0;
464
465  /*
466   * Set up receive buffer size
467   */
468  m8xx.fec.r_buf_size = 0x5f0; /* set to 1520 */
469
470  /*
471   * Allocate mbuf pointers
472   */
473  sc->rxMbuf = malloc (sc->rxBdCount * sizeof *sc->rxMbuf,
474                       M_MBUF, M_NOWAIT);
475  sc->txMbuf = malloc (sc->txBdCount * sizeof *sc->txMbuf,
476                       M_MBUF, M_NOWAIT);
477  if (!sc->rxMbuf || !sc->txMbuf)
478    rtems_panic ("No memory for mbuf pointers");
479 
480  /*
481   * Set receiver and transmitter buffer descriptor bases
482   */
483  sc->rxBdBase = m8xx_bd_allocate(sc->rxBdCount);
484  sc->txBdBase = m8xx_bd_allocate(sc->txBdCount);
485  m8xx.fec.r_des_start = (int)sc->rxBdBase;
486  m8xx.fec.x_des_start = (int)sc->txBdBase;
487 
488  /*
489   * Set up Receive Control Register:
490   *   Not promiscuous mode
491   *   MII mode
492   *   Half duplex
493   *   No loopback
494   */
495  m8xx.fec.r_cntrl = 0x00000006;
496
497  /*
498   * Set up Transmit Control Register:
499   *   Half duplex
500   *   No heartbeat
501   */
502  m8xx.fec.x_cntrl = 0x00000000;
503
504  /*
505   * Set up DMA function code:
506   *   Big-endian
507   *   DMA functino code = 0
508   */
509  m8xx.fec.fun_code = 0x78000000;
510
511  /*
512   * Initialize SDMA configuration register
513   *   SDMA ignores FRZ
514   *   FEC not aggressive
515   *   FEC arbitration ID = 0 => U-bus arbitration = 6
516   *   RISC arbitration ID = 1 => U-bus arbitration = 5
517   */
518  m8xx.sdcr = 1;
519
520  /*
521   * Set MII speed to 2.5 MHz for 25 Mhz system clock 
522   */
523  m8xx.fec.mii_speed = 0x0a;
524  m8xx.fec.mii_data = 0x58021000;
525 
526  /*
527   * Set up receive buffer descriptors
528   */
529  for (i = 0 ; i < sc->rxBdCount ; i++)
530    (sc->rxBdBase + i)->status = 0;
531 
532  /*
533   * Set up transmit buffer descriptors
534   */
535  for (i = 0 ; i < sc->txBdCount ; i++) {
536    (sc->txBdBase + i)->status = 0;
537    sc->txMbuf[i] = NULL;
538  }
539  sc->txBdHead = sc->txBdTail = 0;
540  sc->txBdActiveCount = 0;
541 
542 
543
544  /*
545   * Mask all FEC interrupts and clear events
546   */
547  m8xx.fec.imask = M8xx_FEC_IEVENT_TFINT |
548                   M8xx_FEC_IEVENT_RFINT;
549  m8xx.fec.ievent = ~0;
550
551  /*
552   * Set up interrupts
553   */
554  status = rtems_interrupt_catch (m860_fec_interrupt_handler,
555                                  PPC_IRQ_LVL2,
556                                  &old_handler);
557  if (status != RTEMS_SUCCESSFUL)
558    rtems_panic ("Can't attach M860 FEC interrupt handler: %s\n",
559                 rtems_status_text (status));
560
561  m8xx.simask |= M8xx_SIMASK_LVM2;
562
563}
564
565
566/*
567 * Soak up buffer descriptors that have been sent
568 * Note that a buffer descriptor can't be retired as soon as it becomes
569 * ready.  The MC68360 Errata (May 96) says that, "If an Ethernet frame is
570 *  made up of multiple buffers, the user should not reuse the first buffer
571 * descriptor until the last buffer descriptor of the frame has had its
572 * ready bit cleared by the CPM".
573 */
574static void
575m860Enet_retire_tx_bd (struct m860_enet_struct *sc)
576{
577  rtems_unsigned16 status;
578  int i;
579  int nRetired;
580  struct mbuf *m, *n;
581 
582  i = sc->txBdTail;
583  nRetired = 0;
584  while ((sc->txBdActiveCount != 0)
585         &&  (((status = (sc->txBdBase + i)->status) & M8xx_BD_READY) == 0)) {
586    /*
587     * See if anything went wrong
588     */
589    if (status & (M8xx_BD_DEFER |
590                  M8xx_BD_HEARTBEAT |
591                  M8xx_BD_LATE_COLLISION |
592                  M8xx_BD_RETRY_LIMIT |
593                  M8xx_BD_UNDERRUN |
594                  M8xx_BD_CARRIER_LOST)) {
595      /*
596       * Check for errors which stop the transmitter.
597       */
598      if (status & (M8xx_BD_LATE_COLLISION |
599                    M8xx_BD_RETRY_LIMIT |
600                    M8xx_BD_UNDERRUN)) {
601        if (status & M8xx_BD_LATE_COLLISION)
602          enet_driver[0].txLateCollision++;
603        if (status & M8xx_BD_RETRY_LIMIT)
604          enet_driver[0].txRetryLimit++;
605        if (status & M8xx_BD_UNDERRUN)
606          enet_driver[0].txUnderrun++;
607       
608        /*
609         * Restart the transmitter
610         */
611        /* FIXME: this should get executed only if using the SCC */
612        m8xx_cp_execute_cmd (M8xx_CR_OP_RESTART_TX | M8xx_CR_CHAN_SCC1);
613      }
614      if (status & M8xx_BD_DEFER)
615        enet_driver[0].txDeferred++;
616      if (status & M8xx_BD_HEARTBEAT)
617        enet_driver[0].txHeartbeat++;
618      if (status & M8xx_BD_CARRIER_LOST)
619        enet_driver[0].txLostCarrier++;
620    }
621    nRetired++;
622    if (status & M8xx_BD_LAST) {
623      /*
624       * A full frame has been transmitted.
625       * Free all the associated buffer descriptors.
626       */
627      sc->txBdActiveCount -= nRetired;
628      while (nRetired) {
629        nRetired--;
630        m = sc->txMbuf[sc->txBdTail];
631        MFREE (m, n);
632        if (++sc->txBdTail == sc->txBdCount)
633          sc->txBdTail = 0;
634      }
635    }
636    if (++i == sc->txBdCount)
637      i = 0;
638  }
639}
640
641/*
642 * reader task
643 */
644static void
645scc_rxDaemon (void *arg)
646{
647  struct m860_enet_struct *sc = (struct m860_enet_struct *)arg;
648  struct ifnet *ifp = &sc->arpcom.ac_if;
649  struct mbuf *m;
650  rtems_unsigned16 status;
651  m8xxBufferDescriptor_t *rxBd;
652  int rxBdIndex;
653 
654  /*
655   * Allocate space for incoming packets and start reception
656   */
657  for (rxBdIndex = 0 ; ;) {
658    rxBd = sc->rxBdBase + rxBdIndex;
659    MGETHDR (m, M_WAIT, MT_DATA);
660    MCLGET (m, M_WAIT);
661    m->m_pkthdr.rcvif = ifp;
662    sc->rxMbuf[rxBdIndex] = m;
663    rxBd->buffer = mtod (m, void *);
664    rxBd->status = M8xx_BD_EMPTY | M8xx_BD_INTERRUPT;
665    if (++rxBdIndex == sc->rxBdCount) {
666      rxBd->status |= M8xx_BD_WRAP;
667      break;
668    }
669  }
670 
671  /*
672   * Input packet handling loop
673   */
674  rxBdIndex = 0;
675  for (;;) {
676    rxBd = sc->rxBdBase + rxBdIndex;
677   
678    /*
679     * Wait for packet if there's not one ready
680     */
681    if ((status = rxBd->status) & M8xx_BD_EMPTY) {
682      /*
683       * Clear old events
684       */
685      m8xx.scc1.scce = 0x8;
686     
687      /*
688       * Wait for packet
689       * Note that the buffer descriptor is checked
690       * *before* the event wait -- this catches the
691       * possibility that a packet arrived between the
692       * `if' above, and the clearing of the event register.
693       */
694      while ((status = rxBd->status) & M8xx_BD_EMPTY) {
695        rtems_event_set events;
696       
697        /*
698         * Unmask RXF (Full frame received) event
699         */
700        m8xx.scc1.sccm |= 0x8;
701       
702        rtems_bsdnet_event_receive (INTERRUPT_EVENT,
703                                    RTEMS_WAIT|RTEMS_EVENT_ANY,
704                                    RTEMS_NO_TIMEOUT,
705                                    &events);
706      }
707    }
708   
709    /*
710     * Check that packet is valid
711     */
712    if ((status & (M8xx_BD_LAST |
713                   M8xx_BD_FIRST_IN_FRAME |
714                   M8xx_BD_LONG |
715                   M8xx_BD_NONALIGNED |
716                   M8xx_BD_SHORT |
717                   M8xx_BD_CRC_ERROR |
718                   M8xx_BD_OVERRUN |
719                   M8xx_BD_COLLISION)) ==
720        (M8xx_BD_LAST |
721         M8xx_BD_FIRST_IN_FRAME)) {
722      /*
723       * Pass the packet up the chain.
724       * FIXME: Packet filtering hook could be done here.
725       */
726      struct ether_header *eh;
727     
728      m = sc->rxMbuf[rxBdIndex];
729      m->m_len = m->m_pkthdr.len = rxBd->length -
730        sizeof(rtems_unsigned32) -
731        sizeof(struct ether_header);
732      eh = mtod (m, struct ether_header *);
733      m->m_data += sizeof(struct ether_header);
734      ether_input (ifp, eh, m);
735     
736      /*
737       * Allocate a new mbuf
738       */
739      MGETHDR (m, M_WAIT, MT_DATA);
740      MCLGET (m, M_WAIT);
741      m->m_pkthdr.rcvif = ifp;
742      sc->rxMbuf[rxBdIndex] = m;
743      rxBd->buffer = mtod (m, void *);
744    }
745    else {
746      /*
747       * Something went wrong with the reception
748       */
749      if (!(status & M8xx_BD_LAST))
750        sc->rxNotLast++;
751      if (!(status & M8xx_BD_FIRST_IN_FRAME))
752        sc->rxNotFirst++;
753      if (status & M8xx_BD_LONG)
754        sc->rxGiant++;
755      if (status & M8xx_BD_NONALIGNED)
756        sc->rxNonOctet++;
757      if (status & M8xx_BD_SHORT)
758        sc->rxRunt++;
759      if (status & M8xx_BD_CRC_ERROR)
760        sc->rxBadCRC++;
761      if (status & M8xx_BD_OVERRUN)
762        sc->rxOverrun++;
763      if (status & M8xx_BD_COLLISION)
764        sc->rxCollision++;
765    }
766   
767    /*
768     * Reenable the buffer descriptor
769     */
770    rxBd->status = (status & (M8xx_BD_WRAP | M8xx_BD_INTERRUPT)) |
771                    M8xx_BD_EMPTY;
772   
773    /*
774     * Move to next buffer descriptor
775     */
776    if (++rxBdIndex == sc->rxBdCount)
777      rxBdIndex = 0;
778  }
779}
780
781static void
782fec_rxDaemon (void *arg)
783{
784  struct m860_enet_struct *sc = (struct m860_enet_struct *)arg;
785  struct ifnet *ifp = &sc->arpcom.ac_if;
786  struct mbuf *m;
787  rtems_unsigned16 status;
788  m8xxBufferDescriptor_t *rxBd;
789  int rxBdIndex;
790 
791  /*
792   * Allocate space for incoming packets and start reception
793   */
794  for (rxBdIndex = 0 ; ;) {
795    rxBd = sc->rxBdBase + rxBdIndex;
796    MGETHDR (m, M_WAIT, MT_DATA);
797    MCLGET (m, M_WAIT);
798    m->m_pkthdr.rcvif = ifp;
799    sc->rxMbuf[rxBdIndex] = m;
800    rxBd->buffer = mtod (m, void *);
801    rxBd->status = M8xx_BD_EMPTY;
802    m8xx.fec.r_des_active = 0x1000000;
803    if (++rxBdIndex == sc->rxBdCount) {
804      rxBd->status |= M8xx_BD_WRAP;
805      break;
806    }
807  }
808 
809  /*
810   * Input packet handling loop
811   */
812  rxBdIndex = 0;
813  for (;;) {
814    rxBd = sc->rxBdBase + rxBdIndex;
815   
816    /*
817     * Wait for packet if there's not one ready
818     */
819    if ((status = rxBd->status) & M8xx_BD_EMPTY) {
820      /*
821       * Clear old events
822       */
823      m8xx.fec.ievent = M8xx_FEC_IEVENT_RFINT;
824     
825      /*
826       * Wait for packet
827       * Note that the buffer descriptor is checked
828       * *before* the event wait -- this catches the
829       * possibility that a packet arrived between the
830       * `if' above, and the clearing of the event register.
831       */
832      while ((status = rxBd->status) & M8xx_BD_EMPTY) {
833        rtems_event_set events;
834       
835        /*
836         * Unmask RXF (Full frame received) event
837         */
838        m8xx.fec.ievent |= M8xx_FEC_IEVENT_RFINT;
839       
840        rtems_bsdnet_event_receive (INTERRUPT_EVENT,
841                                    RTEMS_WAIT|RTEMS_EVENT_ANY,
842                                    RTEMS_NO_TIMEOUT,
843                                    &events);
844      }
845    }
846   
847    /*
848     * Check that packet is valid
849     */
850    if (status & M8xx_BD_LAST) {
851      /*
852       * Pass the packet up the chain.
853       * FIXME: Packet filtering hook could be done here.
854       */
855      struct ether_header *eh;
856     
857      m = sc->rxMbuf[rxBdIndex];
858      m->m_len = m->m_pkthdr.len = rxBd->length -
859        sizeof(rtems_unsigned32) -
860        sizeof(struct ether_header);
861      eh = mtod (m, struct ether_header *);
862      m->m_data += sizeof(struct ether_header);
863      ether_input (ifp, eh, m);
864     
865      /*
866       * Allocate a new mbuf
867       */
868      MGETHDR (m, M_WAIT, MT_DATA);
869      MCLGET (m, M_WAIT);
870      m->m_pkthdr.rcvif = ifp;
871      sc->rxMbuf[rxBdIndex] = m;
872      rxBd->buffer = mtod (m, void *);
873    }
874    else {
875      /*
876       * Something went wrong with the reception
877       */
878      if (!(status & M8xx_BD_LAST))
879        sc->rxNotLast++;
880      if (status & M8xx_BD_LONG)
881        sc->rxGiant++;
882      if (status & M8xx_BD_NONALIGNED)
883        sc->rxNonOctet++;
884      if (status & M8xx_BD_SHORT)
885        sc->rxRunt++;
886      if (status & M8xx_BD_CRC_ERROR)
887        sc->rxBadCRC++;
888      if (status & M8xx_BD_OVERRUN)
889        sc->rxOverrun++;
890      if (status & M8xx_BD_COLLISION)
891        sc->rxCollision++;
892    }
893    /*
894     * Reenable the buffer descriptor
895     */
896    rxBd->status = (status & M8xx_BD_WRAP) |
897                    M8xx_BD_EMPTY;
898    m8xx.fec.r_des_active = 0x1000000;
899    /*
900     * Move to next buffer descriptor
901     */
902    if (++rxBdIndex == sc->rxBdCount)
903      rxBdIndex = 0;
904  }
905}
906
907static void
908scc_sendpacket (struct ifnet *ifp, struct mbuf *m)
909{
910  struct m860_enet_struct *sc = ifp->if_softc;
911  volatile m8xxBufferDescriptor_t *firstTxBd, *txBd;
912  struct mbuf *l = NULL;
913  rtems_unsigned16 status;
914  int nAdded;
915 
916  /*
917   * Free up buffer descriptors
918   */
919  m860Enet_retire_tx_bd (sc);
920 
921  /*
922   * Set up the transmit buffer descriptors.
923   * No need to pad out short packets since the
924   * hardware takes care of that automatically.
925   * No need to copy the packet to a contiguous buffer
926   * since the hardware is capable of scatter/gather DMA.
927   */
928  nAdded = 0;
929  txBd = firstTxBd = sc->txBdBase + sc->txBdHead;
930  for (;;) {
931    /*
932     * Wait for buffer descriptor to become available.
933     */
934    if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
935      /*
936       * Clear old events
937       */
938      m8xx.scc1.scce = 0x12;
939     
940      /*
941       * Wait for buffer descriptor to become available.
942       * Note that the buffer descriptors are checked
943       * *before* * entering the wait loop -- this catches
944       * the possibility that a buffer descriptor became
945       * available between the `if' above, and the clearing
946       * of the event register.
947       * This is to catch the case where the transmitter
948       * stops in the middle of a frame -- and only the
949       * last buffer descriptor in a frame can generate
950       * an interrupt.
951       */
952      m860Enet_retire_tx_bd (sc);
953      while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
954        rtems_event_set events;
955       
956                                /*
957                                 * Unmask TXB (buffer transmitted) and
958                                 * TXE (transmitter error) events.
959                                 */
960        m8xx.scc1.sccm |= 0x12;
961        rtems_bsdnet_event_receive (INTERRUPT_EVENT,
962                                    RTEMS_WAIT|RTEMS_EVENT_ANY,
963                                    RTEMS_NO_TIMEOUT,
964                                    &events);
965        m860Enet_retire_tx_bd (sc);
966      }
967    }
968   
969    /*
970     * Don't set the READY flag till the
971     * whole packet has been readied.
972     */
973    status = nAdded ? M8xx_BD_READY : 0;
974   
975    /*
976     *  FIXME: Why not deal with empty mbufs at at higher level?
977     * The IP fragmentation routine in ip_output
978     * can produce packet fragments with zero length.
979     * I think that ip_output should be changed to get
980     * rid of these zero-length mbufs, but for now,
981     * I'll deal with them here.
982     */
983    if (m->m_len) {
984      /*
985       * Fill in the buffer descriptor
986       */
987      txBd->buffer = mtod (m, void *);
988      txBd->length = m->m_len;
989      sc->txMbuf[sc->txBdHead] = m;
990      nAdded++;
991      if (++sc->txBdHead == sc->txBdCount) {
992        status |= M8xx_BD_WRAP;
993        sc->txBdHead = 0;
994      }
995      l = m;
996      m = m->m_next;
997    }
998    else {
999      /*
1000       * Just toss empty mbufs
1001       */
1002      struct mbuf *n;
1003      MFREE (m, n);
1004      m = n;
1005      if (l != NULL)
1006        l->m_next = m;
1007    }
1008   
1009    /*
1010     * Set the transmit buffer status.
1011     * Break out of the loop if this mbuf is the last in the frame.
1012     */
1013    if (m == NULL) {
1014      if (nAdded) {
1015        status |= M8xx_BD_PAD | M8xx_BD_LAST | M8xx_BD_TX_CRC | M8xx_BD_INTERRUPT;
1016        txBd->status = status;
1017        firstTxBd->status |= M8xx_BD_READY;
1018        sc->txBdActiveCount += nAdded;
1019      }
1020      break;
1021    }
1022    txBd->status = status;
1023    txBd = sc->txBdBase + sc->txBdHead;
1024  }
1025}
1026
1027static void
1028fec_sendpacket (struct ifnet *ifp, struct mbuf *m)
1029{
1030  struct m860_enet_struct *sc = ifp->if_softc;
1031  volatile m8xxBufferDescriptor_t *firstTxBd, *txBd;
1032  /*  struct mbuf *l = NULL; */
1033  rtems_unsigned16 status;
1034  int nAdded;
1035 
1036  /*
1037   * Free up buffer descriptors
1038   */
1039  m8xxEnet_retire_tx_bd (sc);
1040 
1041  /*
1042   * Set up the transmit buffer descriptors.
1043   * No need to pad out short packets since the
1044   * hardware takes care of that automatically.
1045   * No need to copy the packet to a contiguous buffer
1046   * since the hardware is capable of scatter/gather DMA.
1047   */
1048  nAdded = 0;
1049  txBd = firstTxBd = sc->txBdBase + sc->txBdHead;
1050  for (;;) {
1051    /*
1052     * Wait for buffer descriptor to become available.
1053     */
1054    if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
1055      /*
1056       * Clear old events
1057       */
1058      m8xx.fec.ievent = M8xx_FEC_IEVENT_TFINT;
1059     
1060      /*
1061       * Wait for buffer descriptor to become available.
1062       * Note that the buffer descriptors are checked
1063       * *before* * entering the wait loop -- this catches
1064       * the possibility that a buffer descriptor became
1065       * available between the `if' above, and the clearing
1066       * of the event register.
1067       * This is to catch the case where the transmitter
1068       * stops in the middle of a frame -- and only the
1069       * last buffer descriptor in a frame can generate
1070       * an interrupt.
1071       */
1072      m860Enet_retire_tx_bd (sc);
1073      while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
1074        rtems_event_set events;
1075       
1076        /*
1077         * Unmask TXB (buffer transmitted) and
1078         * TXE (transmitter error) events.
1079         */
1080        m8xx.fec.ievent |= M8xx_FEC_IEVENT_TFINT;
1081        rtems_bsdnet_event_receive (INTERRUPT_EVENT,
1082                                    RTEMS_WAIT|RTEMS_EVENT_ANY,
1083                                    RTEMS_NO_TIMEOUT,
1084                                    &events);
1085        m860Enet_retire_tx_bd (sc);
1086      }
1087    }
1088   
1089    /*
1090     * Don't set the READY flag till the
1091     * whole packet has been readied.
1092     */
1093    status = nAdded ? M8xx_BD_READY : 0;
1094   
1095    /*
1096     *  FIXME: Why not deal with empty mbufs at at higher level?
1097     * The IP fragmentation routine in ip_output
1098     * can produce packet fragments with zero length.
1099     * I think that ip_output should be changed to get
1100     * rid of these zero-length mbufs, but for now,
1101     * I'll deal with them here.
1102     */
1103    if (m->m_len) {
1104      /*
1105       * Fill in the buffer descriptor
1106       */
1107      txBd->buffer = mtod (m, void *);
1108      txBd->length = m->m_len;
1109      sc->txMbuf[sc->txBdHead] = m;
1110      nAdded++;
1111      if (++sc->txBdHead == sc->txBdCount) {
1112        status |= M8xx_BD_WRAP;
1113        sc->txBdHead = 0;
1114      }
1115      /*      l = m;*/
1116      m = m->m_next;
1117    }
1118    else {
1119      /*
1120       * Just toss empty mbufs
1121       */
1122      struct mbuf *n;
1123      MFREE (m, n);
1124      m = n;
1125      /*
1126      if (l != NULL)
1127        l->m_next = m;
1128      */
1129    }
1130   
1131    /*
1132     * Set the transmit buffer status.
1133     * Break out of the loop if this mbuf is the last in the frame.
1134     */
1135    if (m == NULL) {
1136      if (nAdded) {
1137        status |= M8xx_BD_LAST | M8xx_BD_TX_CRC;
1138        txBd->status = status;
1139        firstTxBd->status |= M8xx_BD_READY;
1140        m8xx.fec.x_des_active = 0x1000000;
1141        sc->txBdActiveCount += nAdded;
1142      }
1143      break;
1144    }
1145    txBd->status = status;
1146    txBd = sc->txBdBase + sc->txBdHead;
1147  }
1148}
1149
1150/*
1151 * Driver transmit daemon
1152 */
1153void
1154scc_txDaemon (void *arg)
1155{
1156  struct m860_enet_struct *sc = (struct m860_enet_struct *)arg;
1157  struct ifnet *ifp = &sc->arpcom.ac_if;
1158  struct mbuf *m;
1159  rtems_event_set events;
1160 
1161  for (;;) {
1162    /*
1163     * Wait for packet
1164     */
1165    rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events);
1166   
1167    /*
1168     * Send packets till queue is empty
1169     */
1170    for (;;) {
1171      /*
1172       * Get the next mbuf chain to transmit.
1173       */
1174      IF_DEQUEUE(&ifp->if_snd, m);
1175      if (!m)
1176        break;
1177      scc_sendpacket (ifp, m);
1178    }
1179    ifp->if_flags &= ~IFF_OACTIVE;
1180  }
1181}
1182
1183void
1184fec_txDaemon (void *arg)
1185{
1186  struct m860_enet_struct *sc = (struct m860_enet_struct *)arg;
1187  struct ifnet *ifp = &sc->arpcom.ac_if;
1188  struct mbuf *m;
1189  rtems_event_set events;
1190 
1191  for (;;) {
1192    /*
1193     * Wait for packet
1194     */
1195    rtems_bsdnet_event_receive (START_TRANSMIT_EVENT,
1196                                RTEMS_EVENT_ANY | RTEMS_WAIT,
1197                                RTEMS_NO_TIMEOUT,
1198                                &events);
1199   
1200    /*
1201     * Send packets till queue is empty
1202     */
1203    for (;;) {
1204      /*
1205       * Get the next mbuf chain to transmit.
1206       */
1207      IF_DEQUEUE(&ifp->if_snd, m);
1208      if (!m)
1209        break;
1210      fec_sendpacket (ifp, m);
1211    }
1212    ifp->if_flags &= ~IFF_OACTIVE;
1213  }
1214}
1215
1216/*
1217 * Send packet (caller provides header).
1218 */
1219static void
1220m860_enet_start (struct ifnet *ifp)
1221{
1222  struct m860_enet_struct *sc = ifp->if_softc;
1223 
1224  rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
1225  ifp->if_flags |= IFF_OACTIVE;
1226}
1227
1228/*
1229 * Initialize and start the device
1230 */
1231static void
1232scc_init (void *arg)
1233{
1234  struct m860_enet_struct *sc = arg;
1235  struct ifnet *ifp = &sc->arpcom.ac_if;
1236 
1237  if (sc->txDaemonTid == 0) {
1238   
1239    /*
1240     * Set up SCC hardware
1241     */
1242    m860_scc_initialize_hardware (sc);
1243   
1244    /*
1245     * Start driver tasks
1246     */
1247    sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, scc_txDaemon, sc);
1248    sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, scc_rxDaemon, sc);
1249   
1250  }
1251 
1252  /*
1253   * Set flags appropriately
1254   */
1255  if (ifp->if_flags & IFF_PROMISC)
1256    m8xx.scc1.psmr |= 0x200;
1257  else
1258    m8xx.scc1.psmr &= ~0x200;
1259 
1260  /*
1261   * Tell the world that we're running.
1262   */
1263  ifp->if_flags |= IFF_RUNNING;
1264 
1265  /*
1266   * Enable receiver and transmitter
1267   */
1268  m8xx.scc1.gsmr_l |= 0x30;
1269}
1270
1271static void
1272fec_init (void *arg)
1273{
1274  struct m860_enet_struct *sc = arg;
1275  struct ifnet *ifp = &sc->arpcom.ac_if;
1276 
1277  if (sc->txDaemonTid == 0) {
1278   
1279    /*
1280     * Set up SCC hardware
1281     */
1282    m860_fec_initialize_hardware (sc);
1283   
1284    /*
1285     * Start driver tasks
1286     */
1287    sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, fec_txDaemon, sc);
1288    sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, fec_rxDaemon, sc);
1289   
1290  }
1291 
1292  /*
1293   * Set flags appropriately
1294   */
1295  if (ifp->if_flags & IFF_PROMISC)
1296    m8xx.fec.r_cntrl |= 0x8;
1297  else
1298    m8xx.fec.r_cntrl &= ~0x8;
1299
1300 
1301  /*
1302   * Tell the world that we're running.
1303   */
1304  ifp->if_flags |= IFF_RUNNING;
1305 
1306  /*
1307   * Enable receiver and transmitter
1308   */
1309  m8xx.fec.ecntrl = 0x2;
1310}
1311
1312
1313/*
1314 * Stop the device
1315 */
1316static void
1317scc_stop (struct m860_enet_struct *sc)
1318{
1319  struct ifnet *ifp = &sc->arpcom.ac_if;
1320 
1321  ifp->if_flags &= ~IFF_RUNNING;
1322 
1323  /*
1324   * Shut down receiver and transmitter
1325   */
1326  m8xx.scc1.gsmr_l &= ~0x30;
1327}
1328
1329static void
1330fec_stop (struct m860_enet_struct *sc)
1331{
1332  struct ifnet *ifp = &sc->arpcom.ac_if;
1333 
1334  ifp->if_flags &= ~IFF_RUNNING;
1335 
1336  /*
1337   * Shut down receiver and transmitter
1338   */
1339  m8xx.fec.ecntrl = 0x0;
1340}
1341
1342/*
1343 * Show interface statistics
1344 */
1345static void
1346enet_stats (struct m860_enet_struct *sc)
1347{
1348  printf ("      Rx Interrupts:%-8lu", sc->rxInterrupts);
1349  printf ("       Not First:%-8lu", sc->rxNotFirst);
1350  printf ("        Not Last:%-8lu\n", sc->rxNotLast);
1351  printf ("              Giant:%-8lu", sc->rxGiant);
1352  printf ("            Runt:%-8lu", sc->rxRunt);
1353  printf ("       Non-octet:%-8lu\n", sc->rxNonOctet);
1354  printf ("            Bad CRC:%-8lu", sc->rxBadCRC);
1355  printf ("         Overrun:%-8lu", sc->rxOverrun);
1356  printf ("       Collision:%-8lu\n", sc->rxCollision);
1357  printf ("          Discarded:%-8lu\n", (unsigned long)m8xx.scc1p.un.ethernet.disfc);
1358 
1359  printf ("      Tx Interrupts:%-8lu", sc->txInterrupts);
1360  printf ("        Deferred:%-8lu", sc->txDeferred);
1361  printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat);
1362  printf ("         No Carrier:%-8lu", sc->txLostCarrier);
1363  printf ("Retransmit Limit:%-8lu", sc->txRetryLimit);
1364  printf ("  Late Collision:%-8lu\n", sc->txLateCollision);
1365  printf ("           Underrun:%-8lu", sc->txUnderrun);
1366  printf (" Raw output wait:%-8lu\n", sc->txRawWait);
1367}
1368
1369/*
1370 * Driver ioctl handler
1371 */
1372static int
1373scc_ioctl (struct ifnet *ifp, int command, caddr_t data)
1374{
1375  struct m860_enet_struct *sc = ifp->if_softc;
1376  int error = 0;
1377 
1378  switch (command) {
1379  case SIOCGIFADDR:
1380  case SIOCSIFADDR:
1381    ether_ioctl (ifp, command, data);
1382    break;
1383   
1384  case SIOCSIFFLAGS:
1385    switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
1386    case IFF_RUNNING:
1387      scc_stop (sc);
1388      break;
1389     
1390    case IFF_UP:
1391      scc_init (sc);
1392      break;
1393     
1394    case IFF_UP | IFF_RUNNING:
1395      scc_stop (sc);
1396      scc_init (sc);
1397      break;
1398     
1399    default:
1400      break;
1401    }
1402    break;
1403   
1404  case SIO_RTEMS_SHOW_STATS:
1405    enet_stats (sc);
1406    break;
1407   
1408    /*
1409     * FIXME: All sorts of multicast commands need to be added here!
1410     */
1411  default:
1412    error = EINVAL;
1413    break;
1414  }
1415  return error;
1416}
1417
1418static int
1419fec_ioctl (struct ifnet *ifp, int command, caddr_t data)
1420{
1421  struct m860_enet_struct *sc = ifp->if_softc;
1422  int error = 0;
1423 
1424  switch (command) {
1425  case SIOCGIFADDR:
1426  case SIOCSIFADDR:
1427    ether_ioctl (ifp, command, data);
1428    break;
1429   
1430  case SIOCSIFFLAGS:
1431    switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
1432    case IFF_RUNNING:
1433      fec_stop (sc);
1434      break;
1435     
1436    case IFF_UP:
1437      fec_init (sc);
1438      break;
1439     
1440    case IFF_UP | IFF_RUNNING:
1441      fec_stop (sc);
1442      fec_init (sc);
1443      break;
1444     
1445    default:
1446      break;
1447    }
1448    break;
1449   
1450  case SIO_RTEMS_SHOW_STATS:
1451    enet_stats (sc);
1452    break;
1453   
1454    /*
1455     * FIXME: All sorts of multicast commands need to be added here!
1456     */
1457  default:
1458    error = EINVAL;
1459    break;
1460  }
1461  return error;
1462}
1463
1464/*
1465 * Attach an SCC driver to the system
1466 */
1467int
1468rtems_scc1_driver_attach (struct rtems_bsdnet_ifconfig *config)
1469{
1470  struct m860_enet_struct *sc;
1471  struct ifnet *ifp;
1472  int mtu;
1473  int i;
1474 
1475  /*
1476   * Find a free driver
1477   */
1478  for (i = 0 ; i < NIFACES ; i++) {
1479    sc = &enet_driver[i];
1480    ifp = &sc->arpcom.ac_if;
1481    if (ifp->if_softc == NULL)
1482      break;
1483  }
1484  if (i >= NIFACES) {
1485    printf ("Too many SCC drivers.\n");
1486    return 0;
1487  }
1488 
1489  /*
1490   * Process options
1491   */
1492  if (config->hardware_address) {
1493    memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
1494  }
1495  else {
1496    sc->arpcom.ac_enaddr[0] = 0x44;
1497    sc->arpcom.ac_enaddr[1] = 0x22;
1498    sc->arpcom.ac_enaddr[2] = 0x33;
1499    sc->arpcom.ac_enaddr[3] = 0x33;
1500    sc->arpcom.ac_enaddr[4] = 0x22;
1501    sc->arpcom.ac_enaddr[5] = 0x44;
1502  }
1503  if (config->mtu)
1504    mtu = config->mtu;
1505  else
1506    mtu = ETHERMTU;
1507  if (config->rbuf_count)
1508    sc->rxBdCount = config->rbuf_count;
1509  else
1510    sc->rxBdCount = RX_BUF_COUNT;
1511  if (config->xbuf_count)
1512    sc->txBdCount = config->xbuf_count;
1513  else
1514    sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF;
1515  sc->acceptBroadcast = !config->ignore_broadcast;
1516 
1517  /*
1518   * Set up network interface values
1519   */
1520  ifp->if_softc = sc;
1521  ifp->if_unit = i + 1;
1522  ifp->if_name = "eth";
1523  ifp->if_mtu = mtu;
1524  ifp->if_init = scc_init;
1525  ifp->if_ioctl = scc_ioctl;
1526  ifp->if_start = m860_enet_start;
1527  ifp->if_output = ether_output;
1528  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
1529  if (ifp->if_snd.ifq_maxlen == 0)
1530    ifp->if_snd.ifq_maxlen = ifqmaxlen;
1531 
1532  /*
1533   * Attach the interface
1534   */
1535  if_attach (ifp);
1536  ether_ifattach (ifp);
1537  return 1;
1538};
1539
1540int
1541rtems_fec_driver_attach (struct rtems_bsdnet_ifconfig *config)
1542{
1543  struct m860_enet_struct *sc;
1544  struct ifnet *ifp;
1545  int mtu;
1546 
1547  /*
1548   * Find a free driver
1549   */
1550  sc = &enet_driver[0];
1551  ifp = &sc->arpcom.ac_if;
1552  if (ifp->if_softc != NULL)
1553    return 0;
1554
1555 
1556  /*
1557   * Process options
1558   */
1559  if (config->hardware_address) {
1560    memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
1561  }
1562  else {
1563    sc->arpcom.ac_enaddr[0] = 0x44;
1564    sc->arpcom.ac_enaddr[1] = 0x22;
1565    sc->arpcom.ac_enaddr[2] = 0x33;
1566    sc->arpcom.ac_enaddr[3] = 0x33;
1567    sc->arpcom.ac_enaddr[4] = 0x22;
1568    sc->arpcom.ac_enaddr[5] = 0x44;
1569  }
1570  if (config->mtu)
1571    mtu = config->mtu;
1572  else
1573    mtu = ETHERMTU;
1574  if (config->rbuf_count)
1575    sc->rxBdCount = config->rbuf_count;
1576  else
1577    sc->rxBdCount = RX_BUF_COUNT;
1578  if (config->xbuf_count)
1579    sc->txBdCount = config->xbuf_count;
1580  else
1581    sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF;
1582  sc->acceptBroadcast = !config->ignore_broadcast;
1583 
1584  /*
1585   * Set up network interface values
1586   */
1587  ifp->if_softc = sc;
1588  ifp->if_unit = 1;
1589  ifp->if_name = "eth";
1590  ifp->if_mtu = mtu;
1591  ifp->if_init = fec_init;
1592  ifp->if_ioctl = fec_ioctl;
1593  ifp->if_start = m860_enet_start;
1594  ifp->if_output = ether_output;
1595  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
1596  if (ifp->if_snd.ifq_maxlen == 0)
1597    ifp->if_snd.ifq_maxlen = ifqmaxlen;
1598 
1599  /*
1600   * Attach the interface
1601   */
1602  if_attach (ifp);
1603  ether_ifattach (ifp);
1604  return 1;
1605};
1606
1607int
1608rtems_enet_driver_attach (struct rtems_bsdnet_ifconfig *config)
1609{
1610  int i;
1611
1612  if ((m8xx.fec.mii_data & 0xffff) == 0x2000) {
1613/*    rtems_scc1_driver_attach(config);*/
1614    return rtems_fec_driver_attach(config);
1615  }
1616  else {
1617    return rtems_scc1_driver_attach(config);
1618  }
1619}
Note: See TracBrowser for help on using the repository browser.