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

4.104.114.84.95
Last change on this file since 35bb69b was 35bb69b, checked in by Joel Sherrill <joel.sherrill@…>, on Apr 6, 2001 at 3:52:03 PM

2001-03-30 Eric Valette <valette@…>

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