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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [powerpc/] [eth_comm/] [network/] [network.c] - Blame information for rev 173

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
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: network.c,v 1.2 2001-09-27 12:00:35 chris Exp $
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
 */
73
struct 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
};
110
static struct m860_enet_struct enet_driver[NIFACES];
111
 
112
/*
113
 * SCC1 interrupt handler
114
 */
115
static rtems_isr
116
m860_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
 */
149
static rtems_isr
150
m860_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
 */
174
static void
175
m860_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
 
407
static void
408
m860_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
 */
575
static void
576
m860Enet_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
 */
645
static void
646
scc_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
 
782
static void
783
fec_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
 
908
static void
909
scc_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
 
1028
static void
1029
fec_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
 */
1154
void
1155
scc_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
 
1184
void
1185
fec_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
 */
1220
static void
1221
m860_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
 */
1232
static void
1233
scc_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
 
1272
static void
1273
fec_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
 */
1317
static void
1318
scc_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
 
1330
static void
1331
fec_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
 */
1346
static void
1347
enet_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
 */
1373
static int
1374
scc_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
 
1419
static int
1420
fec_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
 */
1468
int
1469
rtems_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
 
1541
int
1542
rtems_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
 
1608
int
1609
rtems_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
}

powered by: WebSVN 2.1.0

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