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

4.104.114.84.95
Last change on this file since bbb71a15 was bbb71a15, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 1, 2002 at 9:54:20 PM

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

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