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

4.104.114.84.95
Last change on this file since 4486b18 was 4486b18, checked in by Joel Sherrill <joel.sherrill@…>, on 11/04/02 at 14:27:31

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