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

4.104.114.84.9
Last change on this file since 1740467b was 1740467b, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 4, 2002 at 10:18:26 PM

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

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