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

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

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

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