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

4.104.114.84.95
Last change on this file since 52471f60 was 52471f60, checked in by Joel Sherrill <joel.sherrill@…>, on 11/04/02 at 22:17:51

2002-11-04 Joel Sherrill <joel@…>

  • network/network.c: Removed warnings.
  • 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#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  /*
454   * Set SIU interrupt level to LVL2
455   * 
456   */
457  m8xx.fec.ivec = ((((unsigned) BSP_FAST_ETHERNET_CTRL)/2) << 29);
458 
459  /*
460   * Set the TX and RX fifo sizes. For now, we'll split it evenly
461   */
462  /* If you uncomment these, the FEC will not work right.
463  m8xx.fec.r_fstart = ((m8xx.fec.r_bound & 0x3ff) >> 2) & 0x3ff;
464  m8xx.fec.x_fstart = 0;
465  */
466
467  /*
468   * Set our physical address
469   */
470  hwaddr = sc->arpcom.ac_enaddr;
471 
472  m8xx.fec.addr_low = (hwaddr[0] << 24) | (hwaddr[1] << 16) |
473                      (hwaddr[2] << 8)  | (hwaddr[3] << 0);
474  m8xx.fec.addr_high = (hwaddr[4] << 24) | (hwaddr[5] << 16);
475
476  /*
477   * Clear the hash table
478   */
479  m8xx.fec.hash_table_high = 0;
480  m8xx.fec.hash_table_low  = 0;
481
482  /*
483   * Set up receive buffer size
484   */
485  m8xx.fec.r_buf_size = 0x5f0; /* set to 1520 */
486
487  /*
488   * Allocate mbuf pointers
489   */
490  sc->rxMbuf = malloc (sc->rxBdCount * sizeof *sc->rxMbuf,
491                       M_MBUF, M_NOWAIT);
492  sc->txMbuf = malloc (sc->txBdCount * sizeof *sc->txMbuf,
493                       M_MBUF, M_NOWAIT);
494  if (!sc->rxMbuf || !sc->txMbuf)
495    rtems_panic ("No memory for mbuf pointers",0);
496 
497  /*
498   * Set receiver and transmitter buffer descriptor bases
499   */
500  sc->rxBdBase = m8xx_bd_allocate(sc->rxBdCount);
501  sc->txBdBase = m8xx_bd_allocate(sc->txBdCount);
502  m8xx.fec.r_des_start = (int)sc->rxBdBase;
503  m8xx.fec.x_des_start = (int)sc->txBdBase;
504 
505  /*
506   * Set up Receive Control Register:
507   *   Not promiscuous mode
508   *   MII mode
509   *   Half duplex
510   *   No loopback
511   */
512  m8xx.fec.r_cntrl = 0x00000006;
513
514  /*
515   * Set up Transmit Control Register:
516   *   Half duplex
517   *   No heartbeat
518   */
519  m8xx.fec.x_cntrl = 0x00000000;
520
521  /*
522   * Set up DMA function code:
523   *   Big-endian
524   *   DMA functino code = 0
525   */
526  m8xx.fec.fun_code = 0x78000000;
527
528  /*
529   * Initialize SDMA configuration register
530   *   SDMA ignores FRZ
531   *   FEC not aggressive
532   *   FEC arbitration ID = 0 => U-bus arbitration = 6
533   *   RISC arbitration ID = 1 => U-bus arbitration = 5
534   */
535  m8xx.sdcr = 1;
536
537  /*
538   * Set MII speed to 2.5 MHz for 25 Mhz system clock 
539   */
540  m8xx.fec.mii_speed = 0x0a;
541  m8xx.fec.mii_data = 0x58021000;
542 
543  /*
544   * Set up receive buffer descriptors
545   */
546  for (i = 0 ; i < sc->rxBdCount ; i++)
547    (sc->rxBdBase + i)->status = 0;
548 
549  /*
550   * Set up transmit buffer descriptors
551   */
552  for (i = 0 ; i < sc->txBdCount ; i++) {
553    (sc->txBdBase + i)->status = 0;
554    sc->txMbuf[i] = NULL;
555  }
556  sc->txBdHead = sc->txBdTail = 0;
557  sc->txBdActiveCount = 0;
558 
559 
560
561  /*
562   * Mask all FEC interrupts and clear events
563   */
564  m8xx.fec.imask = M8xx_FEC_IEVENT_TFINT |
565                   M8xx_FEC_IEVENT_RFINT;
566  m8xx.fec.ievent = ~0;
567
568  /*
569   * Set up interrupts
570   */
571  if (!BSP_install_rtems_irq_handler (&ethernetFECIrqData))
572    rtems_panic ("Can't attach M860 FEC interrupt handler\n", 0);
573
574}
575
576
577/*
578 * Soak up buffer descriptors that have been sent
579 * Note that a buffer descriptor can't be retired as soon as it becomes
580 * ready.  The MC68360 Errata (May 96) says that, "If an Ethernet frame is
581 *  made up of multiple buffers, the user should not reuse the first buffer
582 * descriptor until the last buffer descriptor of the frame has had its
583 * ready bit cleared by the CPM".
584 */
585static void
586m860Enet_retire_tx_bd (struct m860_enet_struct *sc)
587{
588  rtems_unsigned16 status;
589  int i;
590  int nRetired;
591  struct mbuf *m, *n;
592 
593  i = sc->txBdTail;
594  nRetired = 0;
595  while ((sc->txBdActiveCount != 0)
596         &&  (((status = (sc->txBdBase + i)->status) & M8xx_BD_READY) == 0)) {
597    /*
598     * See if anything went wrong
599     */
600    if (status & (M8xx_BD_DEFER |
601                  M8xx_BD_HEARTBEAT |
602                  M8xx_BD_LATE_COLLISION |
603                  M8xx_BD_RETRY_LIMIT |
604                  M8xx_BD_UNDERRUN |
605                  M8xx_BD_CARRIER_LOST)) {
606      /*
607       * Check for errors which stop the transmitter.
608       */
609      if (status & (M8xx_BD_LATE_COLLISION |
610                    M8xx_BD_RETRY_LIMIT |
611                    M8xx_BD_UNDERRUN)) {
612        if (status & M8xx_BD_LATE_COLLISION)
613          enet_driver[0].txLateCollision++;
614        if (status & M8xx_BD_RETRY_LIMIT)
615          enet_driver[0].txRetryLimit++;
616        if (status & M8xx_BD_UNDERRUN)
617          enet_driver[0].txUnderrun++;
618       
619        /*
620         * Restart the transmitter
621         */
622        /* FIXME: this should get executed only if using the SCC */
623        m8xx_cp_execute_cmd (M8xx_CR_OP_RESTART_TX | M8xx_CR_CHAN_SCC1);
624      }
625      if (status & M8xx_BD_DEFER)
626        enet_driver[0].txDeferred++;
627      if (status & M8xx_BD_HEARTBEAT)
628        enet_driver[0].txHeartbeat++;
629      if (status & M8xx_BD_CARRIER_LOST)
630        enet_driver[0].txLostCarrier++;
631    }
632    nRetired++;
633    if (status & M8xx_BD_LAST) {
634      /*
635       * A full frame has been transmitted.
636       * Free all the associated buffer descriptors.
637       */
638      sc->txBdActiveCount -= nRetired;
639      while (nRetired) {
640        nRetired--;
641        m = sc->txMbuf[sc->txBdTail];
642        MFREE (m, n);
643        if (++sc->txBdTail == sc->txBdCount)
644          sc->txBdTail = 0;
645      }
646    }
647    if (++i == sc->txBdCount)
648      i = 0;
649  }
650}
651
652/*
653 * reader task
654 */
655static void
656scc_rxDaemon (void *arg)
657{
658  struct m860_enet_struct *sc = (struct m860_enet_struct *)arg;
659  struct ifnet *ifp = &sc->arpcom.ac_if;
660  struct mbuf *m;
661  rtems_unsigned16 status;
662  m8xxBufferDescriptor_t *rxBd;
663  int rxBdIndex;
664 
665  /*
666   * Allocate space for incoming packets and start reception
667   */
668  for (rxBdIndex = 0 ; ;) {
669    rxBd = sc->rxBdBase + rxBdIndex;
670    MGETHDR (m, M_WAIT, MT_DATA);
671    MCLGET (m, M_WAIT);
672    m->m_pkthdr.rcvif = ifp;
673    sc->rxMbuf[rxBdIndex] = m;
674    rxBd->buffer = mtod (m, void *);
675    rxBd->status = M8xx_BD_EMPTY | M8xx_BD_INTERRUPT;
676    if (++rxBdIndex == sc->rxBdCount) {
677      rxBd->status |= M8xx_BD_WRAP;
678      break;
679    }
680  }
681 
682  /*
683   * Input packet handling loop
684   */
685  rxBdIndex = 0;
686  for (;;) {
687    rxBd = sc->rxBdBase + rxBdIndex;
688   
689    /*
690     * Wait for packet if there's not one ready
691     */
692    if ((status = rxBd->status) & M8xx_BD_EMPTY) {
693      /*
694       * Clear old events
695       */
696      m8xx.scc1.scce = 0x8;
697     
698      /*
699       * Wait for packet
700       * Note that the buffer descriptor is checked
701       * *before* the event wait -- this catches the
702       * possibility that a packet arrived between the
703       * `if' above, and the clearing of the event register.
704       */
705      while ((status = rxBd->status) & M8xx_BD_EMPTY) {
706        rtems_event_set events;
707       
708        /*
709         * Unmask RXF (Full frame received) event
710         */
711        m8xx.scc1.sccm |= 0x8;
712       
713        rtems_bsdnet_event_receive (INTERRUPT_EVENT,
714                                    RTEMS_WAIT|RTEMS_EVENT_ANY,
715                                    RTEMS_NO_TIMEOUT,
716                                    &events);
717      }
718    }
719   
720    /*
721     * Check that packet is valid
722     */
723    if ((status & (M8xx_BD_LAST |
724                   M8xx_BD_FIRST_IN_FRAME |
725                   M8xx_BD_LONG |
726                   M8xx_BD_NONALIGNED |
727                   M8xx_BD_SHORT |
728                   M8xx_BD_CRC_ERROR |
729                   M8xx_BD_OVERRUN |
730                   M8xx_BD_COLLISION)) ==
731        (M8xx_BD_LAST |
732         M8xx_BD_FIRST_IN_FRAME)) {
733      /*
734       * Pass the packet up the chain.
735       * FIXME: Packet filtering hook could be done here.
736       */
737      struct ether_header *eh;
738     
739      m = sc->rxMbuf[rxBdIndex];
740      m->m_len = m->m_pkthdr.len = rxBd->length -
741        sizeof(rtems_unsigned32) -
742        sizeof(struct ether_header);
743      eh = mtod (m, struct ether_header *);
744      m->m_data += sizeof(struct ether_header);
745      ether_input (ifp, eh, m);
746     
747      /*
748       * Allocate a new mbuf
749       */
750      MGETHDR (m, M_WAIT, MT_DATA);
751      MCLGET (m, M_WAIT);
752      m->m_pkthdr.rcvif = ifp;
753      sc->rxMbuf[rxBdIndex] = m;
754      rxBd->buffer = mtod (m, void *);
755    }
756    else {
757      /*
758       * Something went wrong with the reception
759       */
760      if (!(status & M8xx_BD_LAST))
761        sc->rxNotLast++;
762      if (!(status & M8xx_BD_FIRST_IN_FRAME))
763        sc->rxNotFirst++;
764      if (status & M8xx_BD_LONG)
765        sc->rxGiant++;
766      if (status & M8xx_BD_NONALIGNED)
767        sc->rxNonOctet++;
768      if (status & M8xx_BD_SHORT)
769        sc->rxRunt++;
770      if (status & M8xx_BD_CRC_ERROR)
771        sc->rxBadCRC++;
772      if (status & M8xx_BD_OVERRUN)
773        sc->rxOverrun++;
774      if (status & M8xx_BD_COLLISION)
775        sc->rxCollision++;
776    }
777   
778    /*
779     * Reenable the buffer descriptor
780     */
781    rxBd->status = (status & (M8xx_BD_WRAP | M8xx_BD_INTERRUPT)) |
782                    M8xx_BD_EMPTY;
783   
784    /*
785     * Move to next buffer descriptor
786     */
787    if (++rxBdIndex == sc->rxBdCount)
788      rxBdIndex = 0;
789  }
790}
791
792static void
793fec_rxDaemon (void *arg)
794{
795  struct m860_enet_struct *sc = (struct m860_enet_struct *)arg;
796  struct ifnet *ifp = &sc->arpcom.ac_if;
797  struct mbuf *m;
798  rtems_unsigned16 status;
799  m8xxBufferDescriptor_t *rxBd;
800  int rxBdIndex;
801 
802  /*
803   * Allocate space for incoming packets and start reception
804   */
805  for (rxBdIndex = 0 ; ;) {
806    rxBd = sc->rxBdBase + rxBdIndex;
807    MGETHDR (m, M_WAIT, MT_DATA);
808    MCLGET (m, M_WAIT);
809    m->m_pkthdr.rcvif = ifp;
810    sc->rxMbuf[rxBdIndex] = m;
811    rxBd->buffer = mtod (m, void *);
812    rxBd->status = M8xx_BD_EMPTY;
813    m8xx.fec.r_des_active = 0x1000000;
814    if (++rxBdIndex == sc->rxBdCount) {
815      rxBd->status |= M8xx_BD_WRAP;
816      break;
817    }
818  }
819 
820  /*
821   * Input packet handling loop
822   */
823  rxBdIndex = 0;
824  for (;;) {
825    rxBd = sc->rxBdBase + rxBdIndex;
826   
827    /*
828     * Wait for packet if there's not one ready
829     */
830    if ((status = rxBd->status) & M8xx_BD_EMPTY) {
831      /*
832       * Clear old events
833       */
834      m8xx.fec.ievent = M8xx_FEC_IEVENT_RFINT;
835     
836      /*
837       * Wait for packet
838       * Note that the buffer descriptor is checked
839       * *before* the event wait -- this catches the
840       * possibility that a packet arrived between the
841       * `if' above, and the clearing of the event register.
842       */
843      while ((status = rxBd->status) & M8xx_BD_EMPTY) {
844        rtems_event_set events;
845       
846        /*
847         * Unmask RXF (Full frame received) event
848         */
849        m8xx.fec.ievent |= M8xx_FEC_IEVENT_RFINT;
850       
851        rtems_bsdnet_event_receive (INTERRUPT_EVENT,
852                                    RTEMS_WAIT|RTEMS_EVENT_ANY,
853                                    RTEMS_NO_TIMEOUT,
854                                    &events);
855      }
856    }
857   
858    /*
859     * Check that packet is valid
860     */
861    if (status & M8xx_BD_LAST) {
862      /*
863       * Pass the packet up the chain.
864       * FIXME: Packet filtering hook could be done here.
865       */
866      struct ether_header *eh;
867     
868      m = sc->rxMbuf[rxBdIndex];
869      m->m_len = m->m_pkthdr.len = rxBd->length -
870        sizeof(rtems_unsigned32) -
871        sizeof(struct ether_header);
872      eh = mtod (m, struct ether_header *);
873      m->m_data += sizeof(struct ether_header);
874      ether_input (ifp, eh, m);
875     
876      /*
877       * Allocate a new mbuf
878       */
879      MGETHDR (m, M_WAIT, MT_DATA);
880      MCLGET (m, M_WAIT);
881      m->m_pkthdr.rcvif = ifp;
882      sc->rxMbuf[rxBdIndex] = m;
883      rxBd->buffer = mtod (m, void *);
884    }
885    else {
886      /*
887       * Something went wrong with the reception
888       */
889      if (!(status & M8xx_BD_LAST))
890        sc->rxNotLast++;
891      if (status & M8xx_BD_LONG)
892        sc->rxGiant++;
893      if (status & M8xx_BD_NONALIGNED)
894        sc->rxNonOctet++;
895      if (status & M8xx_BD_SHORT)
896        sc->rxRunt++;
897      if (status & M8xx_BD_CRC_ERROR)
898        sc->rxBadCRC++;
899      if (status & M8xx_BD_OVERRUN)
900        sc->rxOverrun++;
901      if (status & M8xx_BD_COLLISION)
902        sc->rxCollision++;
903    }
904    /*
905     * Reenable the buffer descriptor
906     */
907    rxBd->status = (status & M8xx_BD_WRAP) |
908                    M8xx_BD_EMPTY;
909    m8xx.fec.r_des_active = 0x1000000;
910    /*
911     * Move to next buffer descriptor
912     */
913    if (++rxBdIndex == sc->rxBdCount)
914      rxBdIndex = 0;
915  }
916}
917
918static void
919scc_sendpacket (struct ifnet *ifp, struct mbuf *m)
920{
921  struct m860_enet_struct *sc = ifp->if_softc;
922  volatile m8xxBufferDescriptor_t *firstTxBd, *txBd;
923  struct mbuf *l = NULL;
924  rtems_unsigned16 status;
925  int nAdded;
926 
927  /*
928   * Free up buffer descriptors
929   */
930  m860Enet_retire_tx_bd (sc);
931 
932  /*
933   * Set up the transmit buffer descriptors.
934   * No need to pad out short packets since the
935   * hardware takes care of that automatically.
936   * No need to copy the packet to a contiguous buffer
937   * since the hardware is capable of scatter/gather DMA.
938   */
939  nAdded = 0;
940  txBd = firstTxBd = sc->txBdBase + sc->txBdHead;
941  for (;;) {
942    /*
943     * Wait for buffer descriptor to become available.
944     */
945    if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
946      /*
947       * Clear old events
948       */
949      m8xx.scc1.scce = 0x12;
950     
951      /*
952       * Wait for buffer descriptor to become available.
953       * Note that the buffer descriptors are checked
954       * *before* * entering the wait loop -- this catches
955       * the possibility that a buffer descriptor became
956       * available between the `if' above, and the clearing
957       * of the event register.
958       * This is to catch the case where the transmitter
959       * stops in the middle of a frame -- and only the
960       * last buffer descriptor in a frame can generate
961       * an interrupt.
962       */
963      m860Enet_retire_tx_bd (sc);
964      while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
965        rtems_event_set events;
966       
967                                /*
968                                 * Unmask TXB (buffer transmitted) and
969                                 * TXE (transmitter error) events.
970                                 */
971        m8xx.scc1.sccm |= 0x12;
972        rtems_bsdnet_event_receive (INTERRUPT_EVENT,
973                                    RTEMS_WAIT|RTEMS_EVENT_ANY,
974                                    RTEMS_NO_TIMEOUT,
975                                    &events);
976        m860Enet_retire_tx_bd (sc);
977      }
978    }
979   
980    /*
981     * Don't set the READY flag till the
982     * whole packet has been readied.
983     */
984    status = nAdded ? M8xx_BD_READY : 0;
985   
986    /*
987     *  FIXME: Why not deal with empty mbufs at at higher level?
988     * The IP fragmentation routine in ip_output
989     * can produce packet fragments with zero length.
990     * I think that ip_output should be changed to get
991     * rid of these zero-length mbufs, but for now,
992     * I'll deal with them here.
993     */
994    if (m->m_len) {
995      /*
996       * Fill in the buffer descriptor
997       */
998      txBd->buffer = mtod (m, void *);
999      txBd->length = m->m_len;
1000      sc->txMbuf[sc->txBdHead] = m;
1001      nAdded++;
1002      if (++sc->txBdHead == sc->txBdCount) {
1003        status |= M8xx_BD_WRAP;
1004        sc->txBdHead = 0;
1005      }
1006      l = m;
1007      m = m->m_next;
1008    }
1009    else {
1010      /*
1011       * Just toss empty mbufs
1012       */
1013      struct mbuf *n;
1014      MFREE (m, n);
1015      m = n;
1016      if (l != NULL)
1017        l->m_next = m;
1018    }
1019   
1020    /*
1021     * Set the transmit buffer status.
1022     * Break out of the loop if this mbuf is the last in the frame.
1023     */
1024    if (m == NULL) {
1025      if (nAdded) {
1026        status |= M8xx_BD_PAD | M8xx_BD_LAST | M8xx_BD_TX_CRC | M8xx_BD_INTERRUPT;
1027        txBd->status = status;
1028        firstTxBd->status |= M8xx_BD_READY;
1029        sc->txBdActiveCount += nAdded;
1030      }
1031      break;
1032    }
1033    txBd->status = status;
1034    txBd = sc->txBdBase + sc->txBdHead;
1035  }
1036}
1037
1038static void
1039fec_sendpacket (struct ifnet *ifp, struct mbuf *m)
1040{
1041  struct m860_enet_struct *sc = ifp->if_softc;
1042  volatile m8xxBufferDescriptor_t *firstTxBd, *txBd;
1043  /*  struct mbuf *l = NULL; */
1044  rtems_unsigned16 status;
1045  int nAdded;
1046 
1047  /*
1048   * Free up buffer descriptors
1049   */
1050  m860Enet_retire_tx_bd (sc);
1051 
1052  /*
1053   * Set up the transmit buffer descriptors.
1054   * No need to pad out short packets since the
1055   * hardware takes care of that automatically.
1056   * No need to copy the packet to a contiguous buffer
1057   * since the hardware is capable of scatter/gather DMA.
1058   */
1059  nAdded = 0;
1060  txBd = firstTxBd = sc->txBdBase + sc->txBdHead;
1061  for (;;) {
1062    /*
1063     * Wait for buffer descriptor to become available.
1064     */
1065    if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
1066      /*
1067       * Clear old events
1068       */
1069      m8xx.fec.ievent = M8xx_FEC_IEVENT_TFINT;
1070     
1071      /*
1072       * Wait for buffer descriptor to become available.
1073       * Note that the buffer descriptors are checked
1074       * *before* * entering the wait loop -- this catches
1075       * the possibility that a buffer descriptor became
1076       * available between the `if' above, and the clearing
1077       * of the event register.
1078       * This is to catch the case where the transmitter
1079       * stops in the middle of a frame -- and only the
1080       * last buffer descriptor in a frame can generate
1081       * an interrupt.
1082       */
1083      m860Enet_retire_tx_bd (sc);
1084      while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
1085        rtems_event_set events;
1086       
1087        /*
1088         * Unmask TXB (buffer transmitted) and
1089         * TXE (transmitter error) events.
1090         */
1091        m8xx.fec.ievent |= M8xx_FEC_IEVENT_TFINT;
1092        rtems_bsdnet_event_receive (INTERRUPT_EVENT,
1093                                    RTEMS_WAIT|RTEMS_EVENT_ANY,
1094                                    RTEMS_NO_TIMEOUT,
1095                                    &events);
1096        m860Enet_retire_tx_bd (sc);
1097      }
1098    }
1099   
1100    /*
1101     * Don't set the READY flag till the
1102     * whole packet has been readied.
1103     */
1104    status = nAdded ? M8xx_BD_READY : 0;
1105   
1106    /*
1107     *  FIXME: Why not deal with empty mbufs at at higher level?
1108     * The IP fragmentation routine in ip_output
1109     * can produce packet fragments with zero length.
1110     * I think that ip_output should be changed to get
1111     * rid of these zero-length mbufs, but for now,
1112     * I'll deal with them here.
1113     */
1114    if (m->m_len) {
1115      /*
1116       * Fill in the buffer descriptor
1117       */
1118      txBd->buffer = mtod (m, void *);
1119      txBd->length = m->m_len;
1120      sc->txMbuf[sc->txBdHead] = m;
1121      nAdded++;
1122      if (++sc->txBdHead == sc->txBdCount) {
1123        status |= M8xx_BD_WRAP;
1124        sc->txBdHead = 0;
1125      }
1126      /*      l = m;*/
1127      m = m->m_next;
1128    }
1129    else {
1130      /*
1131       * Just toss empty mbufs
1132       */
1133      struct mbuf *n;
1134      MFREE (m, n);
1135      m = n;
1136      /*
1137      if (l != NULL)
1138        l->m_next = m;
1139      */
1140    }
1141   
1142    /*
1143     * Set the transmit buffer status.
1144     * Break out of the loop if this mbuf is the last in the frame.
1145     */
1146    if (m == NULL) {
1147      if (nAdded) {
1148        status |= M8xx_BD_LAST | M8xx_BD_TX_CRC;
1149        txBd->status = status;
1150        firstTxBd->status |= M8xx_BD_READY;
1151        m8xx.fec.x_des_active = 0x1000000;
1152        sc->txBdActiveCount += nAdded;
1153      }
1154      break;
1155    }
1156    txBd->status = status;
1157    txBd = sc->txBdBase + sc->txBdHead;
1158  }
1159}
1160
1161/*
1162 * Driver transmit daemon
1163 */
1164void
1165scc_txDaemon (void *arg)
1166{
1167  struct m860_enet_struct *sc = (struct m860_enet_struct *)arg;
1168  struct ifnet *ifp = &sc->arpcom.ac_if;
1169  struct mbuf *m;
1170  rtems_event_set events;
1171 
1172  for (;;) {
1173    /*
1174     * Wait for packet
1175     */
1176    rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events);
1177   
1178    /*
1179     * Send packets till queue is empty
1180     */
1181    for (;;) {
1182      /*
1183       * Get the next mbuf chain to transmit.
1184       */
1185      IF_DEQUEUE(&ifp->if_snd, m);
1186      if (!m)
1187        break;
1188      scc_sendpacket (ifp, m);
1189    }
1190    ifp->if_flags &= ~IFF_OACTIVE;
1191  }
1192}
1193
1194void
1195fec_txDaemon (void *arg)
1196{
1197  struct m860_enet_struct *sc = (struct m860_enet_struct *)arg;
1198  struct ifnet *ifp = &sc->arpcom.ac_if;
1199  struct mbuf *m;
1200  rtems_event_set events;
1201 
1202  for (;;) {
1203    /*
1204     * Wait for packet
1205     */
1206    rtems_bsdnet_event_receive (START_TRANSMIT_EVENT,
1207                                RTEMS_EVENT_ANY | RTEMS_WAIT,
1208                                RTEMS_NO_TIMEOUT,
1209                                &events);
1210   
1211    /*
1212     * Send packets till queue is empty
1213     */
1214    for (;;) {
1215      /*
1216       * Get the next mbuf chain to transmit.
1217       */
1218      IF_DEQUEUE(&ifp->if_snd, m);
1219      if (!m)
1220        break;
1221      fec_sendpacket (ifp, m);
1222    }
1223    ifp->if_flags &= ~IFF_OACTIVE;
1224  }
1225}
1226
1227/*
1228 * Send packet (caller provides header).
1229 */
1230static void
1231m860_enet_start (struct ifnet *ifp)
1232{
1233  struct m860_enet_struct *sc = ifp->if_softc;
1234 
1235  rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
1236  ifp->if_flags |= IFF_OACTIVE;
1237}
1238
1239/*
1240 * Initialize and start the device
1241 */
1242static void
1243scc_init (void *arg)
1244{
1245  struct m860_enet_struct *sc = arg;
1246  struct ifnet *ifp = &sc->arpcom.ac_if;
1247 
1248  if (sc->txDaemonTid == 0) {
1249   
1250    /*
1251     * Set up SCC hardware
1252     */
1253    m860_scc_initialize_hardware (sc);
1254   
1255    /*
1256     * Start driver tasks
1257     */
1258    sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, scc_txDaemon, sc);
1259    sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, scc_rxDaemon, sc);
1260   
1261  }
1262 
1263  /*
1264   * Set flags appropriately
1265   */
1266  if (ifp->if_flags & IFF_PROMISC)
1267    m8xx.scc1.psmr |= 0x200;
1268  else
1269    m8xx.scc1.psmr &= ~0x200;
1270 
1271  /*
1272   * Tell the world that we're running.
1273   */
1274  ifp->if_flags |= IFF_RUNNING;
1275 
1276  /*
1277   * Enable receiver and transmitter
1278   */
1279  m8xx.scc1.gsmr_l |= 0x30;
1280}
1281
1282static void
1283fec_init (void *arg)
1284{
1285  struct m860_enet_struct *sc = arg;
1286  struct ifnet *ifp = &sc->arpcom.ac_if;
1287 
1288  if (sc->txDaemonTid == 0) {
1289   
1290    /*
1291     * Set up SCC hardware
1292     */
1293    m860_fec_initialize_hardware (sc);
1294   
1295    /*
1296     * Start driver tasks
1297     */
1298    sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, fec_txDaemon, sc);
1299    sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, fec_rxDaemon, sc);
1300   
1301  }
1302 
1303  /*
1304   * Set flags appropriately
1305   */
1306  if (ifp->if_flags & IFF_PROMISC)
1307    m8xx.fec.r_cntrl |= 0x8;
1308  else
1309    m8xx.fec.r_cntrl &= ~0x8;
1310
1311 
1312  /*
1313   * Tell the world that we're running.
1314   */
1315  ifp->if_flags |= IFF_RUNNING;
1316 
1317  /*
1318   * Enable receiver and transmitter
1319   */
1320  m8xx.fec.ecntrl = 0x2;
1321}
1322
1323
1324/*
1325 * Stop the device
1326 */
1327static void
1328scc_stop (struct m860_enet_struct *sc)
1329{
1330  struct ifnet *ifp = &sc->arpcom.ac_if;
1331 
1332  ifp->if_flags &= ~IFF_RUNNING;
1333 
1334  /*
1335   * Shut down receiver and transmitter
1336   */
1337  m8xx.scc1.gsmr_l &= ~0x30;
1338}
1339
1340static void
1341fec_stop (struct m860_enet_struct *sc)
1342{
1343  struct ifnet *ifp = &sc->arpcom.ac_if;
1344 
1345  ifp->if_flags &= ~IFF_RUNNING;
1346 
1347  /*
1348   * Shut down receiver and transmitter
1349   */
1350  m8xx.fec.ecntrl = 0x0;
1351}
1352
1353/*
1354 * Show interface statistics
1355 */
1356static void
1357enet_stats (struct m860_enet_struct *sc)
1358{
1359  printf ("      Rx Interrupts:%-8lu", sc->rxInterrupts);
1360  printf ("       Not First:%-8lu", sc->rxNotFirst);
1361  printf ("        Not Last:%-8lu\n", sc->rxNotLast);
1362  printf ("              Giant:%-8lu", sc->rxGiant);
1363  printf ("            Runt:%-8lu", sc->rxRunt);
1364  printf ("       Non-octet:%-8lu\n", sc->rxNonOctet);
1365  printf ("            Bad CRC:%-8lu", sc->rxBadCRC);
1366  printf ("         Overrun:%-8lu", sc->rxOverrun);
1367  printf ("       Collision:%-8lu\n", sc->rxCollision);
1368  printf ("          Discarded:%-8lu\n", (unsigned long)m8xx.scc1p.un.ethernet.disfc);
1369 
1370  printf ("      Tx Interrupts:%-8lu", sc->txInterrupts);
1371  printf ("        Deferred:%-8lu", sc->txDeferred);
1372  printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat);
1373  printf ("         No Carrier:%-8lu", sc->txLostCarrier);
1374  printf ("Retransmit Limit:%-8lu", sc->txRetryLimit);
1375  printf ("  Late Collision:%-8lu\n", sc->txLateCollision);
1376  printf ("           Underrun:%-8lu", sc->txUnderrun);
1377  printf (" Raw output wait:%-8lu\n", sc->txRawWait);
1378}
1379
1380/*
1381 * Driver ioctl handler
1382 */
1383static int
1384scc_ioctl (struct ifnet *ifp, int command, caddr_t data)
1385{
1386  struct m860_enet_struct *sc = ifp->if_softc;
1387  int error = 0;
1388 
1389  switch (command) {
1390  case SIOCGIFADDR:
1391  case SIOCSIFADDR:
1392    ether_ioctl (ifp, command, data);
1393    break;
1394   
1395  case SIOCSIFFLAGS:
1396    switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
1397    case IFF_RUNNING:
1398      scc_stop (sc);
1399      break;
1400     
1401    case IFF_UP:
1402      scc_init (sc);
1403      break;
1404     
1405    case IFF_UP | IFF_RUNNING:
1406      scc_stop (sc);
1407      scc_init (sc);
1408      break;
1409     
1410    default:
1411      break;
1412    }
1413    break;
1414   
1415  case SIO_RTEMS_SHOW_STATS:
1416    enet_stats (sc);
1417    break;
1418   
1419    /*
1420     * FIXME: All sorts of multicast commands need to be added here!
1421     */
1422  default:
1423    error = EINVAL;
1424    break;
1425  }
1426  return error;
1427}
1428
1429static int
1430fec_ioctl (struct ifnet *ifp, int command, caddr_t data)
1431{
1432  struct m860_enet_struct *sc = ifp->if_softc;
1433  int error = 0;
1434 
1435  switch (command) {
1436  case SIOCGIFADDR:
1437  case SIOCSIFADDR:
1438    ether_ioctl (ifp, command, data);
1439    break;
1440   
1441  case SIOCSIFFLAGS:
1442    switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
1443    case IFF_RUNNING:
1444      fec_stop (sc);
1445      break;
1446     
1447    case IFF_UP:
1448      fec_init (sc);
1449      break;
1450     
1451    case IFF_UP | IFF_RUNNING:
1452      fec_stop (sc);
1453      fec_init (sc);
1454      break;
1455     
1456    default:
1457      break;
1458    }
1459    break;
1460   
1461  case SIO_RTEMS_SHOW_STATS:
1462    enet_stats (sc);
1463    break;
1464   
1465    /*
1466     * FIXME: All sorts of multicast commands need to be added here!
1467     */
1468  default:
1469    error = EINVAL;
1470    break;
1471  }
1472  return error;
1473}
1474
1475/*
1476 * Attach an SCC driver to the system
1477 */
1478int
1479rtems_scc1_driver_attach (struct rtems_bsdnet_ifconfig *config)
1480{
1481  struct m860_enet_struct *sc;
1482  struct ifnet *ifp;
1483  int mtu;
1484  int i;
1485 
1486  /*
1487   * Find a free driver
1488   */
1489  for (i = 0 ; i < NIFACES ; i++) {
1490    sc = &enet_driver[i];
1491    ifp = &sc->arpcom.ac_if;
1492    if (ifp->if_softc == NULL)
1493      break;
1494  }
1495  if (i >= NIFACES) {
1496    printf ("Too many SCC drivers.\n");
1497    return 0;
1498  }
1499 
1500  /*
1501   * Process options
1502   */
1503  if (config->hardware_address) {
1504    memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
1505  }
1506  else {
1507    sc->arpcom.ac_enaddr[0] = 0x44;
1508    sc->arpcom.ac_enaddr[1] = 0x22;
1509    sc->arpcom.ac_enaddr[2] = 0x33;
1510    sc->arpcom.ac_enaddr[3] = 0x33;
1511    sc->arpcom.ac_enaddr[4] = 0x22;
1512    sc->arpcom.ac_enaddr[5] = 0x44;
1513  }
1514  if (config->mtu)
1515    mtu = config->mtu;
1516  else
1517    mtu = ETHERMTU;
1518  if (config->rbuf_count)
1519    sc->rxBdCount = config->rbuf_count;
1520  else
1521    sc->rxBdCount = RX_BUF_COUNT;
1522  if (config->xbuf_count)
1523    sc->txBdCount = config->xbuf_count;
1524  else
1525    sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF;
1526  sc->acceptBroadcast = !config->ignore_broadcast;
1527 
1528  /*
1529   * Set up network interface values
1530   */
1531  ifp->if_softc = sc;
1532  ifp->if_unit = i + 1;
1533  ifp->if_name = "eth";
1534  ifp->if_mtu = mtu;
1535  ifp->if_init = scc_init;
1536  ifp->if_ioctl = scc_ioctl;
1537  ifp->if_start = m860_enet_start;
1538  ifp->if_output = ether_output;
1539  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
1540  if (ifp->if_snd.ifq_maxlen == 0)
1541    ifp->if_snd.ifq_maxlen = ifqmaxlen;
1542 
1543  /*
1544   * Attach the interface
1545   */
1546  if_attach (ifp);
1547  ether_ifattach (ifp);
1548  return 1;
1549};
1550
1551int
1552rtems_fec_driver_attach (struct rtems_bsdnet_ifconfig *config)
1553{
1554  struct m860_enet_struct *sc;
1555  struct ifnet *ifp;
1556  int mtu;
1557 
1558  /*
1559   * Find a free driver
1560   */
1561  sc = &enet_driver[0];
1562  ifp = &sc->arpcom.ac_if;
1563  if (ifp->if_softc != NULL)
1564    return 0;
1565
1566 
1567  /*
1568   * Process options
1569   */
1570  if (config->hardware_address) {
1571    memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
1572  }
1573  else {
1574    sc->arpcom.ac_enaddr[0] = 0x44;
1575    sc->arpcom.ac_enaddr[1] = 0x22;
1576    sc->arpcom.ac_enaddr[2] = 0x33;
1577    sc->arpcom.ac_enaddr[3] = 0x33;
1578    sc->arpcom.ac_enaddr[4] = 0x22;
1579    sc->arpcom.ac_enaddr[5] = 0x44;
1580  }
1581  if (config->mtu)
1582    mtu = config->mtu;
1583  else
1584    mtu = ETHERMTU;
1585  if (config->rbuf_count)
1586    sc->rxBdCount = config->rbuf_count;
1587  else
1588    sc->rxBdCount = RX_BUF_COUNT;
1589  if (config->xbuf_count)
1590    sc->txBdCount = config->xbuf_count;
1591  else
1592    sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF;
1593  sc->acceptBroadcast = !config->ignore_broadcast;
1594 
1595  /*
1596   * Set up network interface values
1597   */
1598  ifp->if_softc = sc;
1599  ifp->if_unit = 1;
1600  ifp->if_name = "eth";
1601  ifp->if_mtu = mtu;
1602  ifp->if_init = fec_init;
1603  ifp->if_ioctl = fec_ioctl;
1604  ifp->if_start = m860_enet_start;
1605  ifp->if_output = ether_output;
1606  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
1607  if (ifp->if_snd.ifq_maxlen == 0)
1608    ifp->if_snd.ifq_maxlen = ifqmaxlen;
1609 
1610  /*
1611   * Attach the interface
1612   */
1613  if_attach (ifp);
1614  ether_ifattach (ifp);
1615  return 1;
1616};
1617
1618int
1619rtems_enet_driver_attach (struct rtems_bsdnet_ifconfig *config)
1620{
1621  if ((m8xx.fec.mii_data & 0xffff) == 0x2000) {
1622/*    rtems_scc1_driver_attach(config);*/
1623    return rtems_fec_driver_attach(config);
1624  }
1625  else {
1626    return rtems_scc1_driver_attach(config);
1627  }
1628}
Note: See TracBrowser for help on using the repository browser.