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

4.104.114.84.95
Last change on this file since 5e77d129 was 5e77d129, checked in by Joel Sherrill <joel.sherrill@…>, on Jun 14, 2000 at 8:32:44 PM

Patch from John Cotton <john.cotton@…> to correct cache
routine naming to follow RTEMS package/object.method rule.
This patch also eliminated calls to the obsolete routine
m68k_enable_caching.

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