source: rtems/c/src/lib/libbsp/powerpc/eth_comm/network/network.c @ 4e36a2f

4.104.114.84.95
Last change on this file since 4e36a2f was 9e5c391, checked in by Joel Sherrill <joel.sherrill@…>, on 02/18/99 at 15:09:59

Added or corrected CVS Id strings.

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