source: rtems/c/src/lib/libbsp/powerpc/mbx8xx/network/network.c @ bfbc4d3

4.104.114.84.95
Last change on this file since bfbc4d3 was 00ff4cd, checked in by Joel Sherrill <joel.sherrill@…>, on 08/25/00 at 17:24:49

2000-08-11 Charles-Antoine Gauthier <charles.gauthier@…>

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