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

4.104.114.84.95
Last change on this file since f05b2ac was f05b2ac, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/21/04 at 16:01:48

Remove duplicate white lines.

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