OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [lib/] [libbsp/] [powerpc/] [eth_comm/] [network/] [network.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
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
 *  network.c,v 1.5 2001/08/31 14:57:39 joel Exp
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
 */
75
struct 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
};
112
static struct m860_enet_struct enet_driver[NIFACES];
113
 
114
static void  m8xx_scc1_ethernet_on(const rtems_irq_connect_data* ptr)
115
{
116
  /*
117
   * Please put relevant code there
118
   */
119
}
120
 
121
static void  m8xx_scc1_ethernet_off(const rtems_irq_connect_data* ptr)
122
{
123
  /*
124
   * Please put relevant code there
125
   */
126
}
127
 
128
static 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
 */
136
static 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
 */
168
static 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
static 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
 */
199
static void
200
m860_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
}
410
static void m8xx_fec_ethernet_on(){};
411
static void m8xx_fec_ethernet_off(){};
412
static int m8xx_fec_ethernet_isOn (const rtems_irq_connect_data* ptr)
413
{
414
  return BSP_irq_enabled_at_siu (ptr->name);
415
}
416
 
417
static 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
 
425
static void
426
m860_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
 */
587
static void
588
m860Enet_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
 */
657
static void
658
scc_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
 
794
static void
795
fec_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
 
920
static void
921
scc_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
 
1040
static void
1041
fec_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
 */
1166
void
1167
scc_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
 
1196
void
1197
fec_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
 */
1232
static void
1233
m860_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
 */
1244
static void
1245
scc_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
 
1284
static void
1285
fec_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
 */
1329
static void
1330
scc_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
 
1342
static void
1343
fec_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
 */
1358
static void
1359
enet_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
 */
1385
static int
1386
scc_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
 
1431
static int
1432
fec_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
 */
1480
int
1481
rtems_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
 
1553
int
1554
rtems_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
 
1620
int
1621
rtems_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
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.