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

4.104.114.84.95
Last change on this file since 73aef37f was 73aef37f, checked in by Joel Sherrill <joel.sherrill@…>, on 08/31/01 at 14:57:48

2001-08-31 Eric Valette <valette@…>

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