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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libchip/] [network/] [sonic.c] - Blame information for rev 307

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 *       RTEMS NETWORK DRIVER FOR NATIONAL DP83932 `SONIC'
3
 *         SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER
4
 *
5
 *                     REUSABLE CHIP DRIVER
6
 *
7
 * References:
8
 *
9
 *  1) DP83932C-20/25/33 MHz SONIC(TM) Systems-Oriented Network Interface
10
 *     Controller data sheet.  TL/F/10492, RRD-B30M105, National Semiconductor,
11
 *     1995.
12
 *
13
 *  2) Software Driver Programmer's Guide for the DP83932 SONIC(TM),
14
 *     Application Note 746, Wesley Lee and Mike Lui, TL/F/11140,
15
 *     RRD-B30M75, National Semiconductor, March, 1991.
16
 *
17
 *  COPYRIGHT (c) 1989-1997.
18
 *  On-Line Applications Research Corporation (OAR).
19
 *  Copyright assigned to U.S. Government, 1994.
20
 *
21
 *  The license and distribution terms for this file may be
22
 *  found in the file LICENSE in this distribution or at
23
 *  http://www.OARcorp.com/rtems/license.html.
24
 *
25
 *  $Id: sonic.c,v 1.2 2001-09-27 12:01:41 chris Exp $
26
 *
27
 *  This driver was originally written and tested on a DY-4 DMV177,
28
 *  which had a 100 Mhz PPC603e.
29
 *
30
 *  This driver also works with DP83934CVUL-20/25 MHz, tested on
31
 *  Tharsys ERC32 VME board.
32
 *
33
 *  Rehaul to fix lost interrupts and buffers, and to use to use
34
 *  interrupt-free transmission by Jiri, 22/03/1999.
35
 */
36
 
37
#include <rtems.h>
38
#include <rtems/rtems_bsdnet.h>
39
#include <libchip/sonic.h>
40
 
41
#include <stdio.h>
42
 
43
#include <errno.h>
44
#include <rtems/error.h>
45
 
46
#include <sys/param.h>
47
#include <sys/mbuf.h>
48
#include <sys/socket.h>
49
#include <sys/sockio.h>
50
#include <sys/sockio.h>
51
 
52
#include <net/if.h>
53
 
54
#include <netinet/in.h>
55
#include <netinet/if_ether.h>
56
 
57
/*
58
 *  XXX fix this
59
 */
60
 
61
void *set_vector(void *, unsigned32, unsigned32);
62
 
63
#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_MBUFS)
64
#include <rtems/dumpbuf.h>
65
#endif
66
 
67
/*
68
 *  Use the top line if you want more symbols.
69
 */
70
 
71
#define SONIC_STATIC 
72
/* #define SONIC_STATIC static */
73
 
74
/*
75
 * Number of devices supported by this driver
76
 */
77
#ifndef NSONIC
78
# define NSONIC 1
79
#endif
80
 
81
/*
82
 *
83
 * As suggested by National Application Note 746, make the
84
 * receive resource area bigger than the receive descriptor area.
85
 *
86
 * NOTE:  Changing this may break this driver since it currently
87
 *        assumes a 1<->1 mapping.
88
 */
89
#define RRA_EXTRA_COUNT  0
90
 
91
/*
92
 * RTEMS event used by interrupt handler to signal daemons.
93
 */
94
#define INTERRUPT_EVENT  RTEMS_EVENT_1
95
 
96
/*
97
 * RTEMS event used to start transmit daemon.
98
 * This must not be the same as INTERRUPT_EVENT.
99
 */
100
#define START_TRANSMIT_EVENT    RTEMS_EVENT_2
101
 
102
/*
103
 * Largest Ethernet frame.
104
 */
105
#define MAXIMUM_FRAME_SIZE  1518
106
 
107
/*
108
 * Receive buffer size.
109
 * Allow for a pointer, plus a full ethernet frame (including Frame
110
 * Check Sequence) rounded up to a 4-byte boundary.
111
 */
112
#define RBUF_SIZE  ((sizeof (void *) + (MAXIMUM_FRAME_SIZE) + 3) & ~3)
113
/* #define RBUF_WC    ((((MAXIMUM_FRAME_SIZE) + 3) & ~3) / 2) */
114
#define RBUF_WC    (RBUF_SIZE / 2)
115
 
116
/*
117
 * Macros for manipulating 32-bit pointers as 16-bit fragments
118
 */
119
#define LSW(p)   ((rtems_unsigned16)((rtems_unsigned32)(p)))
120
#define MSW(p)   ((rtems_unsigned16)((rtems_unsigned32)(p) >> 16))
121
#define PTR(m,l) ((void*)(((rtems_unsigned16)(m)<<16)|(rtems_unsigned16)(l)))
122
 
123
/*
124
 * Hardware-specific storage
125
 */
126
struct sonic_softc {
127
  /*
128
   * Connection to networking code
129
   * This entry *must* be the first in the sonic_softc structure.
130
   */
131
  struct arpcom                    arpcom;
132
 
133
  /*
134
   * Default location of device registers
135
   * ===CACHE===
136
   * This area must be non-cacheable, guarded.
137
   */
138
  void                             *sonic;
139
 
140
  /*
141
   *  Register access routines
142
   */
143
  sonic_write_register_t           write_register;
144
  sonic_read_register_t            read_register;
145
 
146
  /*
147
   * Interrupt vector
148
   */
149
  rtems_vector_number             vector;
150
 
151
  /*
152
   * Data Configuration Register values
153
   */
154
  rtems_unsigned32                dcr_value;
155
  rtems_unsigned32                dc2_value;
156
 
157
  /*
158
   *  Indicates configuration
159
   */
160
  int                             acceptBroadcast;
161
 
162
  /*
163
   * Task waiting for interrupts
164
   */
165
  rtems_id                        rxDaemonTid;
166
  rtems_id                        txDaemonTid;
167
 
168
  /*
169
   * Receive resource area
170
   */
171
  int                             rdaCount;
172
  ReceiveResourcePointer_t        rsa;
173
  ReceiveResourcePointer_t        rea;
174
  CamDescriptorPointer_t          cdp;
175
  ReceiveDescriptorPointer_t      rda;
176
  ReceiveDescriptorPointer_t      rdp_last;
177
 
178
  /*
179
   * Transmit descriptors
180
   */
181
  int                             tdaCount;
182
  TransmitDescriptorPointer_t     tdaHead;  /* Last filled */
183
  TransmitDescriptorPointer_t     tdaTail;  /* Next to retire */
184
 
185
  /*
186
   * Statistics
187
   */
188
  unsigned long                   Interrupts;
189
  unsigned long                   rxInterrupts;
190
  unsigned long                   rxMissed;
191
  unsigned long                   rxGiant;
192
  unsigned long                   rxNonOctet;
193
  unsigned long                   rxBadCRC;
194
  unsigned long                   rxCollision;
195
 
196
  unsigned long                   txInterrupts;
197
  unsigned long                   txSingleCollision;
198
  unsigned long                   txMultipleCollision;
199
  unsigned long                   txCollision;
200
  unsigned long                   txDeferred;
201
  unsigned long                   txUnderrun;
202
  unsigned long                   txLateCollision;
203
  unsigned long                   txExcessiveCollision;
204
  unsigned long                   txExcessiveDeferral;
205
  unsigned long                   txLostCarrier;
206
  unsigned long                   txRawWait;
207
};
208
SONIC_STATIC struct sonic_softc sonic_softc[NSONIC];
209
 
210
 
211
/*
212
 ******************************************************************
213
 *                                                                *
214
 *                         Debug Routines                         *
215
 *                                                                *
216
 ******************************************************************
217
 */
218
 
219
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS)
220
void sonic_print_tx_descriptor(
221
  TransmitDescriptorPointer_t tdp
222
)
223
{
224
  printf( "TXD ==> %p", tdp );
225
  printf( "  pkt_config = 0x%04x", tdp->pkt_config & 0xffff);
226
  printf( "  pkt_size = 0x%04x\n", tdp->pkt_size & 0xffff );
227
  printf( "  frag_count = %d", tdp->frag_count & 0xffff );
228
  /* could print all the fragments */
229
  printf( "  next = %p", tdp->next );
230
  printf( "  linkp = %p\n", tdp->linkp );
231
  printf( "  mbufp = %p", tdp->mbufp );
232
  if ( tdp->mbufp )
233
    printf( "  mbufp->data = %p", mtod ( tdp->mbufp, void *) );
234
  puts("");
235
}
236
 
237
void sonic_print_rx_descriptor(
238
  ReceiveDescriptorPointer_t rdp
239
)
240
{
241
  printf( "RXD ==> %p\n", rdp );
242
  printf( "  status = 0x%04x", rdp->status & 0xffff );
243
  printf( "  byte_count = 0x%04x\n", rdp->byte_count & 0xffff );
244
  printf( "  pkt = 0x%04x%04x", rdp->pkt_msw, rdp->pkt_lsw );
245
  printf( "  seq_no = %d", rdp->seq_no );
246
  printf( "  link = %d\n", rdp->link );
247
  printf( "  in_use = %d", rdp->in_use );
248
  printf( "  next = %p", rdp->next );
249
  printf( "  mbufp = %p", rdp->mbufp );
250
  if ( rdp->mbufp )
251
    printf( "  mbufp->data = %p", mtod ( rdp->mbufp, void *) );
252
  puts("");
253
}
254
#endif
255
 
256
/*
257
 ******************************************************************
258
 *                                                                *
259
 *                        Support Routines                        *
260
 *                                                                *
261
 ******************************************************************
262
 */
263
 
264
void sonic_enable_interrupts(
265
  struct sonic_softc *sc,
266
  unsigned32  mask
267
)
268
{
269
  void *rp = sc->sonic;
270
  rtems_interrupt_level level;
271
 
272
  rtems_interrupt_disable( level );
273
      (*sc->write_register)(
274
         rp,
275
         SONIC_REG_IMR,
276
         (*sc->read_register)(rp, SONIC_REG_IMR) | mask
277
      );
278
  rtems_interrupt_enable( level );
279
}
280
 
281
void sonic_disable_interrupts(
282
  struct sonic_softc *sc,
283
  unsigned32  mask
284
)
285
{
286
  void *rp = sc->sonic;
287
  rtems_interrupt_level level;
288
 
289
  rtems_interrupt_disable( level );
290
  (*sc->write_register)(
291
         rp,
292
         SONIC_REG_IMR,
293
         (*sc->read_register)(rp, SONIC_REG_IMR) & ~mask
294
      );
295
  rtems_interrupt_enable( level );
296
}
297
 
298
void sonic_clear_interrupts(
299
  struct sonic_softc *sc,
300
  unsigned32  mask
301
)
302
{
303
  void *rp = sc->sonic;
304
  rtems_interrupt_level level;
305
 
306
  rtems_interrupt_disable( level );
307
  (*sc->write_register)( rp, SONIC_REG_ISR, mask);
308
  rtems_interrupt_enable( level );
309
}
310
 
311
void sonic_command(
312
  struct sonic_softc *sc,
313
  unsigned32  mask
314
)
315
{
316
  void *rp = sc->sonic;
317
  rtems_interrupt_level level;
318
 
319
  rtems_interrupt_disable( level );
320
  (*sc->write_register)( rp, SONIC_REG_CR, mask);
321
  rtems_interrupt_enable( level );
322
}
323
 
324
/*
325
 * Allocate non-cacheable memory on a single 64k page.
326
 * Very simple minded -- just keeps trying till the memory is on a single page.
327
 */
328
SONIC_STATIC void * sonic_allocate(unsigned int nbytes)
329
{
330
  void *p;
331
  unsigned long a1, a2;
332
 
333
  for (;;) {
334
    /*
335
     * ===CACHE===
336
     * Change malloc to malloc_noncacheable_guarded.
337
     */
338
    p = malloc( nbytes, M_MBUF, M_NOWAIT );
339
    if (p == NULL)
340
      rtems_panic ("No memory!");
341
    memset (p, '\0', nbytes);
342
    a1 = (unsigned long)p;
343
    a2 = a1 + nbytes - 1;
344
    if ((a1 >> 16) == (a2 >> 16))
345
      break;
346
  }
347
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_ALLOCATE)
348
  printf( "sonic_allocate %d bytes at %p\n", nbytes, p );
349
#endif
350
  return p;
351
}
352
 
353
/*
354
 * Shut down the interface.
355
 */
356
 
357
SONIC_STATIC void sonic_stop (struct sonic_softc *sc)
358
{
359
  struct ifnet *ifp = &sc->arpcom.ac_if;
360
 
361
  ifp->if_flags &= ~IFF_RUNNING;
362
 
363
  /*
364
   * Stop the transmitter and receiver.
365
   */
366
  sonic_command(sc, CR_HTX | CR_RXDIS );
367
}
368
 
369
/*
370
 * Show interface statistics
371
 */
372
SONIC_STATIC void sonic_stats (struct sonic_softc *sc)
373
{
374
  printf (" Total Interrupts:%-8lu", sc->Interrupts);
375
  printf ("    Rx Interrupts:%-8lu", sc->rxInterrupts);
376
  printf ("            Giant:%-8lu", sc->rxGiant);
377
  printf ("        Non-octet:%-8lu\n", sc->rxNonOctet);
378
  printf ("          Bad CRC:%-8lu", sc->rxBadCRC);
379
  printf ("        Collision:%-8lu", sc->rxCollision);
380
  printf ("           Missed:%-8lu\n", sc->rxMissed);
381
 
382
  printf (    "    Tx Interrupts:%-8lu", sc->txInterrupts);
383
  printf (  "           Deferred:%-8lu", sc->txDeferred);
384
  printf ("        Lost Carrier:%-8lu\n", sc->txLostCarrier);
385
  printf (   "Single Collisions:%-8lu", sc->txSingleCollision);
386
  printf ( "Multiple Collisions:%-8lu", sc->txMultipleCollision);
387
  printf ("Excessive Collisions:%-8lu\n", sc->txExcessiveCollision);
388
  printf (   " Total Collisions:%-8lu", sc->txCollision);
389
  printf ( "     Late Collision:%-8lu", sc->txLateCollision);
390
  printf ("            Underrun:%-8lu\n", sc->txUnderrun);
391
  printf (   "  Raw output wait:%-8lu\n", sc->txRawWait);
392
}
393
 
394
/*
395
 ******************************************************************
396
 *                                                                *
397
 *                        Interrupt Handler                       *
398
 *                                                                *
399
 ******************************************************************
400
 */
401
 
402
SONIC_STATIC rtems_isr sonic_interrupt_handler (rtems_vector_number v)
403
{
404
  struct sonic_softc *sc = sonic_softc;
405
  unsigned32 isr, imr;
406
  void *rp;
407
 
408
#if (NSONIC > 1)
409
  /*
410
   * Find the device which requires service
411
   */
412
  for (;;) {
413
    if (sc->vector == v)
414
      break;
415
    if (++sc == &sonic[NSONIC])
416
      return;  /* Spurious interrupt? */
417
  }
418
#endif /* NSONIC > 1 */
419
 
420
  /*
421
   * Get pointer to SONIC registers
422
   */
423
  rp = sc->sonic;
424
 
425
  sc->Interrupts++;
426
 
427
  isr = (*sc->read_register)( rp, SONIC_REG_ISR );
428
  imr = (*sc->read_register)( rp, SONIC_REG_IMR );
429
 
430
  /*
431
   * Packet received or receive buffer area exceeded?
432
   */
433
  if (imr & isr & (IMR_PRXEN | IMR_RBAEEN)) {
434
    imr &= ~(IMR_PRXEN | IMR_RBAEEN);
435
    sc->rxInterrupts++;
436
    rtems_event_send (sc->rxDaemonTid, INTERRUPT_EVENT);
437
    (*sc->write_register)( rp, SONIC_REG_IMR, imr );
438
    (*sc->write_register)( rp, SONIC_REG_ISR, isr & ISR_PKTRX );
439
  }
440
 
441
  /*
442
   * Packet started, transmitter done or transmitter error?
443
   * TX interrupts only occur after an error or when all TDA's are
444
   * exhausted and we are waiting for buffer to come free.
445
   */
446
  if (imr & isr & (IMR_PINTEN | IMR_TXEREN)) {
447
    sc->txInterrupts++;
448
    rtems_event_send (sc->txDaemonTid, INTERRUPT_EVENT);
449
    (*sc->write_register)( rp, SONIC_REG_ISR, ISR_PINT | ISR_TXDN | ISR_TXER );
450
  }
451
 
452
}
453
 
454
/*
455
 ******************************************************************
456
 *                                                                *
457
 *                      Transmitter Routines                      *
458
 *                                                                *
459
 ******************************************************************
460
 */
461
 
462
/*
463
 * Soak up transmit descriptors that have been sent.
464
 */
465
 
466
SONIC_STATIC void sonic_retire_tda (struct sonic_softc *sc)
467
{
468
  rtems_unsigned16 status;
469
  unsigned int collisions;
470
  struct mbuf *m, *n;
471
 
472
  /*
473
   * Repeat for all completed transmit descriptors.
474
   */
475
  while ((status = sc->tdaTail->status) != 0) {
476
 
477
#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)
478
    printf( "retire TDA %p (0x%04x)\n", sc->tdaTail, status );
479
#endif
480
 
481
#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)
482
    /*
483
     *  If there is an error that was not a collision,
484
     *  then someone may want to see it.
485
     */
486
 
487
    if ( (status & ~(TDA_STATUS_COLLISION_MASK|TDA_STATUS_DEF)) != 0x0001 )
488
      printf( "ERROR: retire TDA %p (0x%08x)\n",
489
                sc->tdaTail, sc->tdaTail->status );
490
#endif
491
 
492
    /*
493
     * Check for errors which stop the transmitter.
494
     */
495
    if (status & (TDA_STATUS_EXD |
496
        TDA_STATUS_EXC |
497
        TDA_STATUS_FU |
498
        TDA_STATUS_BCM)) {
499
      /*
500
       * Restart the transmitter if there are
501
       * packets waiting to go.
502
       */
503
      rtems_unsigned16 link;
504
#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)
505
      printf("restarting sonic after error\n");
506
#endif
507
 
508
      link = *(sc->tdaTail->linkp);
509
 
510
      if ((link & TDA_LINK_EOL) == 0) {
511
        void *rp = sc->sonic;
512
 
513
        (*sc->write_register)( rp, SONIC_REG_CTDA, link );
514
        sonic_command(sc, CR_TXP );
515
      }
516
    }
517
 
518
    /*
519
     * Update network statistics
520
     */
521
    collisions = (status & TDA_STATUS_COLLISION_MASK) >> TDA_STATUS_COLLISION_SHIFT;
522
    if (collisions) {
523
      if (collisions == 1)
524
        sc->txSingleCollision++;
525
      else
526
        sc->txMultipleCollision++;
527
      sc->txCollision += collisions;
528
    }
529
    if (status & TDA_STATUS_EXC)
530
      sc->txExcessiveCollision++;
531
    if (status & TDA_STATUS_OWC)
532
      sc->txLateCollision++;
533
    if (status & TDA_STATUS_EXD)
534
      sc->txExcessiveDeferral++;
535
    if (status & TDA_STATUS_DEF)
536
      sc->txDeferred++;
537
    if (status & TDA_STATUS_FU)
538
      sc->txUnderrun++;
539
    if (status & TDA_STATUS_CRSL)
540
      sc->txLostCarrier++;
541
 
542
    /*
543
     *  Free the packet and reset a couple of fields
544
     */
545
    m = sc->tdaTail->mbufp;
546
    while ( m ) {
547
      MFREE(m, n);
548
      m = n;
549
    }
550
 
551
    /*
552
    sc->tdaTail->frag[0].frag_link = LSW(sc->tdaTail->link_pad);
553
    sc->tdaTail->frag_count        = 0;
554
    */
555
    sc->tdaTail->status        = 0;
556
 
557
    /*
558
     * Move to the next transmit descriptor
559
     */
560
    sc->tdaTail = sc->tdaTail->next;
561
#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)
562
    printf( "next TDA %p\n", sc->tdaTail );
563
#endif
564
  }
565
}
566
 
567
/*
568
 * Send packet
569
 */
570
SONIC_STATIC void sonic_sendpacket (struct ifnet *ifp, struct mbuf *m)
571
{
572
  struct sonic_softc *sc = ifp->if_softc;
573
  struct mbuf *l = NULL;
574
  TransmitDescriptorPointer_t tdp;
575
  volatile struct TransmitDescriptorFragLink *fp;
576
  unsigned int packetSize;
577
  int i;
578
  rtems_event_set events;
579
  static char padBuf[64];
580
 
581
  /* printf( "sonic_sendpacket %p\n", m ); */
582
 
583
 
584
  /*
585
   * Wait for transmit descriptor to become available. Only retire TDA's
586
   * if there are no more free buffers to minimize TX latency. Retire TDA'a
587
   * on the way out.
588
   */
589
 
590
  while (sc->tdaHead->next->status != 0) {
591
 
592
  /*
593
   * Free up transmit descriptors
594
   */
595
    sonic_retire_tda (sc);
596
 
597
    if (sc->tdaHead->next->status == 0)
598
      break;
599
 
600
#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)
601
    printf("blocking until TDAs are available\n");
602
#endif
603
      /*
604
       * Enable PINT interrupts.
605
    sonic_clear_interrupts( sc, ISR_PINT );
606
    sonic_enable_interrupts( sc, IMR_PINTEN );
607
       */
608
 
609
      /*
610
       * Wait for PINT TX interrupt. Every fourth TX buffer will raise PINT.
611
       */
612
    rtems_bsdnet_event_receive (INTERRUPT_EVENT,
613
            RTEMS_WAIT|RTEMS_EVENT_ANY,
614
            RTEMS_NO_TIMEOUT,
615
            &events);
616
    sonic_disable_interrupts( sc, IMR_PINTEN );
617
    sonic_retire_tda (sc);
618
  }
619
 
620
  /*
621
   * Fill in the transmit descriptor fragment descriptors.
622
   * ===CACHE===
623
   * If data cache is operating in write-back mode, flush cached
624
   * data to memory.
625
   */
626
  tdp = sc->tdaHead->next;
627
  tdp->mbufp = m;
628
  packetSize = 0;
629
  fp = tdp->frag;
630
  for (i = 0 ; i < MAXIMUM_FRAGS_PER_DESCRIPTOR ; i++, fp++) {
631
    /*
632
     * Throw away empty mbufs
633
     */
634
    if (m->m_len) {
635
      void *p = mtod (m, void *);
636
      fp->frag_lsw = LSW(p);
637
      fp->frag_msw = MSW(p);
638
      fp->frag_size = m->m_len;
639
      packetSize += m->m_len;
640
#if (SONIC_DEBUG & SONIC_DEBUG_FRAGMENTS)
641
      printf( "fp %p 0x%04x%04x %d=%d .. %d\n",
642
        fp, fp->frag_msw, fp->frag_lsw, fp->frag_size, m->m_len, packetSize );
643
#endif
644
#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_TX_MBUFS)
645
      Dump_Buffer(
646
        p,
647
        (fp->frag_size > MAXIMUM_FRAME_SIZE) ? MAXIMUM_FRAME_SIZE : fp->frag_size
648
      );
649
#endif
650
      l = m;
651
      m = m->m_next;
652
    }
653
    else {
654
      struct mbuf *n;
655
      MFREE (m, n);
656
      m = n;
657
      if (l != NULL)
658
        l->m_next = m;
659
    }
660
    /*
661
     * Break out of the loop if this mbuf is the last in the frame.
662
     */
663
    if (m == NULL)
664
      break;
665
  }
666
 
667
  /*
668
   * Pad short packets.
669
   */
670
  if  ((packetSize < 64) && (i < MAXIMUM_FRAGS_PER_DESCRIPTOR)) {
671
    int padSize = 64 - packetSize;
672
    fp++;
673
    fp->frag_lsw = LSW(padBuf);
674
    fp->frag_msw = MSW(padBuf);
675
    fp->frag_size = padSize;
676
#if (SONIC_DEBUG & SONIC_DEBUG_FRAGMENTS)
677
    printf( "PAD fp %p 0x%04x%04x %d\n",
678
         fp, fp->frag_msw, fp->frag_lsw, fp->frag_size );
679
#endif
680
    packetSize += padSize;
681
    i++;
682
  }
683
 
684
  /*
685
   * Fill Transmit Descriptor
686
   */
687
  tdp->pkt_size = packetSize;
688
  tdp->frag_count = i + 1;
689
  tdp->status = 0;
690
 
691
  /*
692
   * Chain onto list and start transmission.
693
   */
694
 
695
  tdp->linkp = &(fp+1)->frag_link;
696
  *tdp->linkp = LSW(tdp->next) | TDA_LINK_EOL;
697
  if ( sc->tdaHead->frag_count )
698
    *sc->tdaHead->linkp &= ~TDA_LINK_EOL;
699
  sc->tdaHead = tdp;
700
 
701
  /* Start transmission */
702
 
703
  sonic_command(sc, CR_TXP );
704
 
705
  /*
706
   * Free up transmit descriptors on the way out.
707
   */
708
  sonic_retire_tda (sc);
709
}
710
 
711
/*
712
 * Driver transmit daemon
713
 */
714
SONIC_STATIC void sonic_txDaemon (void *arg)
715
{
716
  struct sonic_softc *sc = (struct sonic_softc *)arg;
717
  struct ifnet *ifp = &sc->arpcom.ac_if;
718
  struct mbuf *m;
719
  rtems_event_set events;
720
 
721
  for (;;) {
722
    /*
723
     * Wait for packet
724
     */
725
    rtems_bsdnet_event_receive (
726
       START_TRANSMIT_EVENT,
727
       RTEMS_EVENT_ANY | RTEMS_WAIT,
728
       RTEMS_NO_TIMEOUT,
729
       &events
730
    );
731
 
732
    /*
733
     * Send packets till queue is empty
734
     */
735
    for (;;) {
736
      /*
737
       * Get the next mbuf chain to transmit.
738
       */
739
      IF_DEQUEUE(&ifp->if_snd, m);
740
      if (!m)
741
        break;
742
      sonic_sendpacket (ifp, m);
743
    }
744
    ifp->if_flags &= ~IFF_OACTIVE;
745
  }
746
}
747
 
748
/*
749
 ******************************************************************
750
 *                                                                *
751
 *                        Receiver Routines                       *
752
 *                                                                *
753
 ******************************************************************
754
 */
755
 
756
/*
757
 * Wait for SONIC to hand over a Receive Descriptor.
758
 */
759
 
760
SONIC_STATIC void sonic_rda_wait(
761
  struct sonic_softc *sc,
762
  ReceiveDescriptorPointer_t rdp
763
)
764
{
765
  int i;
766
  void *rp = sc->sonic;
767
  rtems_event_set events;
768
 
769
  /*
770
   * Wait for Receive Descriptor.
771
   * The order of the tests is very important.
772
   *    The RDA is checked after RBAE is detected.  This ensures that
773
   *    the driver processes all RDA entries before reusing the RRA
774
   *    entry holding the giant packet.
775
   *    The event wait is done after the RDA and RBAE checks.  This
776
   *    catches the possibility that a Receive Descriptor became ready
777
   *    between the call to this function and the clearing of the
778
   *    interrupt status register bit.
779
   */
780
  for (;;) {
781
    /*
782
     * Has a giant packet arrived?
783
     * The National DP83932C data sheet is very vague on what
784
     * happens under this condition.  The description of the
785
     * Interrupt Status Register (Section 4.3.6) states,
786
     * ``Reception is aborted and the SONIC fetches the next
787
     * available resource descriptors in the RRA.  The buffer
788
     * space is not re-used and an RDA is not setup for the
789
     * truncated packet.''
790
     * I take ``Reception is aborted''  to mean that the RXEN
791
     * bit in the Command Register is cleared and must be set
792
     * by the driver to begin reception again.
793
     * Unfortunately, an alternative interpretation could be
794
     * that only reception of the current packet is aborted.
795
     * This would be more difficult to recover from....
796
     */
797
    if ((*sc->read_register)( rp, SONIC_REG_ISR ) & ISR_RBAE) {
798
 
799
#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)
800
      printf( "ERROR: looks like a giant packet -- RBAE\n" );
801
#endif
802
 
803
      /*
804
       * One more check to soak up any Receive Descriptors
805
       * that may already have been handed back to the driver.
806
       */
807
      if (rdp->in_use == RDA_IN_USE) {
808
#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)
809
      printf( "ERROR: nope just an RBAE\n" );
810
#endif
811
        break;
812
      }
813
 
814
      /*
815
       * Check my interpretation of the SONIC manual.
816
       */
817
      if ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_RXEN)
818
        rtems_panic ("SONIC RBAE/RXEN");
819
 
820
      /*
821
       * Update statistics
822
       */
823
      sc->rxGiant++;
824
 
825
      /*
826
       * Reuse receive buffer.
827
       * Again, the manual is subject to interpretation.  The
828
       * RRP register is described as, `the lower address of
829
       * the next descriptor the SONIC will read.''
830
       * Since, acording to the ISR/RBAE notes, the SONIC has
831
       * ``fetched the next available resource descriptor in
832
       * the RRA'', I interpret this to mean that that the
833
       * driver has to move the RRP back *two* entries to
834
       * reuse the receive buffer holding the giant packet.
835
       */
836
      for (i = 0 ; i < 2 ; i++) {
837
        if ((*sc->read_register)( rp, SONIC_REG_RRP ) ==
838
            (*sc->read_register)( rp, SONIC_REG_RSA ))
839
          (*sc->write_register)(
840
            rp,
841
            SONIC_REG_RRP,
842
            (*sc->read_register)( rp, SONIC_REG_REA )
843
          );
844
          (*sc->write_register)(
845
             rp,
846
             SONIC_REG_RRP,
847
             (*sc->read_register)(rp, SONIC_REG_RRP) - sizeof(ReceiveResource_t)
848
          );
849
      }
850
 
851
      /*
852
       * Restart reception
853
       */
854
      sonic_clear_interrupts( sc, ISR_RBAE );
855
      sonic_command( sc, CR_RXEN );
856
    }
857
 
858
    /*
859
     * Has Receive Descriptor become available?
860
     */
861
    if (rdp->in_use == RDA_IN_USE)
862
      break;
863
 
864
    /*
865
     * Enable interrupts.
866
     */
867
    sonic_enable_interrupts( sc, (IMR_PRXEN | IMR_RBAEEN) );
868
 
869
    /*
870
     * Wait for interrupt.
871
     */
872
    rtems_bsdnet_event_receive(
873
      INTERRUPT_EVENT,
874
      RTEMS_WAIT|RTEMS_EVENT_ANY,
875
      RTEMS_NO_TIMEOUT,
876
      &events
877
    );
878
  }
879
#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)
880
  printf( "RDA %p\n", rdp );
881
#endif
882
 
883
#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)
884
    if (rdp->status & 0x000E)
885
      printf( "ERROR: RDA %p (0x%04x)\n", rdp, rdp->status );
886
#endif
887
 
888
}
889
 
890
/*
891
 * SONIC reader task
892
 */
893
SONIC_STATIC void sonic_rxDaemon (void *arg)
894
{
895
  struct sonic_softc *sc = (struct sonic_softc *)arg;
896
  struct ifnet *ifp = &sc->arpcom.ac_if;
897
  void *rp = sc->sonic;
898
  struct mbuf *m;
899
  rtems_unsigned16 status;
900
  ReceiveDescriptorPointer_t rdp;
901
  ReceiveResourcePointer_t rwp, rea;
902
  rtems_unsigned16 newMissedTally, oldMissedTally;
903
 
904
  rwp = sc->rsa;
905
  rea = sc->rea;
906
  rdp = sc->rda;
907
 
908
  /*
909
   * Start the receiver
910
   */
911
  oldMissedTally = (*sc->read_register)( rp, SONIC_REG_MPT );
912
 
913
  /*
914
   * Input packet handling loop
915
   */
916
  for (;;) {
917
    /*
918
     * Wait till SONIC supplies a Receive Descriptor.
919
     */
920
    if (rdp->in_use == RDA_FREE) {
921
      sonic_rda_wait (sc, rdp);
922
    }
923
 
924
#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)
925
    printf( "Incoming packet %p status=0x%04x\n", rdp, rdp->status );
926
#endif
927
 
928
    /*
929
     * Check that packet is valid
930
     */
931
    status = rdp->status;
932
    if (status & RDA_STATUS_PRX) {
933
      struct ether_header *eh;
934
      void *p;
935
 
936
      /*
937
       * Pass the packet up the chain.
938
       * The mbuf count is reduced to remove
939
       * the frame check sequence at the end
940
       * of the packet.
941
       * ===CACHE===
942
       * Invalidate cache entries for this memory.
943
       */
944
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS)
945
      sonic_print_rx_descriptor( rdp );
946
      if ((LSW(rdp->mbufp->m_data) != rdp->pkt_lsw)
947
       || (MSW(rdp->mbufp->m_data) != rdp->pkt_msw))
948
        printf ("SONIC RDA/RRA %p, %08x\n",rdp->mbufp->m_data,(rdp->pkt_msw << 16) |
949
        (rdp->pkt_lsw & 0x0ffff));
950
#endif
951
      rdp->byte_count &= 0x0ffff;    /* ERC32 pollutes msb of byte_count */
952
      m = rdp->mbufp;
953
      m->m_len = m->m_pkthdr.len = rdp->byte_count -
954
                          sizeof(rtems_unsigned32) -
955
                          sizeof(struct ether_header);
956
      eh = mtod (m, struct ether_header *);
957
      m->m_data += sizeof(struct ether_header);
958
 
959
#ifdef CPU_U32_FIX
960
      ipalign(m);       /* Align packet on 32-bit boundary */
961
#endif
962
 
963
#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_RX_MBUFS)
964
      Dump_Buffer( (void *) eh, sizeof(struct ether_header) );
965
      Dump_Buffer( (void *) m, 96 /* m->m_len*/ );
966
#endif
967
 
968
      /* printf( "ether_input %p\n", m ); */
969
      /*
970
      printf( "pkt %p, seq %04x, mbuf %p, m_data %p\n", rdp, rdp->seq_no, m, m->m_data );
971
      printf( "%u, %u\n", ((int*)m->m_data)[6], ((int*)m->m_data)[7]);
972
      */
973
      ether_input (ifp, eh, m);
974
      /*
975
      */
976
 
977
      /*
978
       * Sanity check that Receive Resource Area is
979
       * still in sync with Receive Descriptor Area
980
       * The buffer reported in the Receive Descriptor
981
       * should be the same as the buffer in the Receive
982
       * Resource we are about to reuse.
983
       */
984
/* XXX figure out whether this is valid or not */
985
#if 0
986
      if ((LSW(p) != rwp->buff_ptr_lsw)
987
       || (MSW(p) != rwp->buff_ptr_msw))
988
        rtems_panic ("SONIC RDA/RRA");
989
#endif
990
 
991
      /*
992
       * Allocate a new mbuf.
993
       */
994
 
995
      MGETHDR (m, M_WAIT, MT_DATA);
996
      MCLGET (m, M_WAIT);
997
      m->m_pkthdr.rcvif = ifp;
998
      rdp->mbufp = m;
999
      p = mtod (m, void *);
1000
 
1001
      /*
1002
       * Reuse Receive Resource.
1003
       */
1004
 
1005
      rwp->buff_ptr_lsw = LSW(p);
1006
      rwp->buff_ptr_msw = MSW(p);
1007
      rwp->buff_wc_lsw = RBUF_WC;
1008
      rwp->buff_wc_msw = 0;
1009
      rwp++;
1010
 
1011
      if (rwp == rea) {
1012
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
1013
        printf( "Wrapping RWP from %p to %p\n", rwp, sc->rsa );
1014
#endif
1015
        rwp = sc->rsa;
1016
      }
1017
      (*sc->write_register)( rp, SONIC_REG_RWP , LSW(rwp) );
1018
 
1019
      /*
1020
       * Tell the SONIC to reread the RRA.
1021
       */
1022
      if ((*sc->read_register)( rp, SONIC_REG_ISR ) & ISR_RBE)
1023
      sonic_clear_interrupts( sc, ISR_RBE );
1024
    }
1025
    else {
1026
      if (status & RDA_STATUS_COL)
1027
        sc->rxCollision++;
1028
      if (status & RDA_STATUS_FAER)
1029
        sc->rxNonOctet++;
1030
      else if (status & RDA_STATUS_CRCR)
1031
        sc->rxBadCRC++;
1032
    }
1033
 
1034
    /*
1035
     * Count missed packets
1036
     */
1037
    newMissedTally = (*sc->read_register)( rp, SONIC_REG_MPT );
1038
    if (newMissedTally != oldMissedTally) {
1039
      sc->rxMissed += (newMissedTally - oldMissedTally) & 0xFFFF;
1040
      newMissedTally = oldMissedTally;
1041
    }
1042
 
1043
    /*
1044
     * Move to next receive descriptor and update EOL
1045
     */
1046
 
1047
    rdp->link |= RDA_LINK_EOL;
1048
    rdp->in_use = RDA_FREE;
1049
    sc->rdp_last->link &= ~RDA_LINK_EOL;
1050
    sc->rdp_last = rdp;
1051
    rdp = rdp->next;
1052
 
1053
  }
1054
}
1055
 
1056
/*
1057
 ******************************************************************
1058
 *                                                                *
1059
 *                     Initialization Routines                    *
1060
 *                                                                *
1061
 ******************************************************************
1062
 */
1063
 
1064
/*
1065
 * Initialize the SONIC hardware
1066
 */
1067
SONIC_STATIC void sonic_initialize_hardware(struct sonic_softc *sc)
1068
{
1069
  void *rp = sc->sonic;
1070
  int i;
1071
  unsigned char *hwaddr;
1072
  rtems_isr_entry old_handler;
1073
  TransmitDescriptorPointer_t tdp;
1074
  ReceiveDescriptorPointer_t ordp, rdp;
1075
  ReceiveResourcePointer_t rwp;
1076
  struct mbuf *m;
1077
  void *p;
1078
  CamDescriptorPointer_t cdp;
1079
 
1080
  /*
1081
   *  The Revision B SONIC has a horrible bug known as the "Zero
1082
   *  Length Packet bug".  The initial board used to develop this
1083
   *  driver had a newer revision of the SONIC so there was no reason
1084
   *  to check for this.  If you have the Revision B SONIC chip, then
1085
   *  you need to add some code to the RX path to handle this weirdness.
1086
   */
1087
 
1088
  if ( (*sc->read_register)( rp, SONIC_REG_SR ) <= SONIC_REVISION_B ) {
1089
    rtems_fatal_error_occurred( 0x0BADF00D );  /* don't eat this part :) */
1090
  }
1091
 
1092
  /*
1093
   *  Set up circular linked list in Transmit Descriptor Area.
1094
   *  Use the PINT bit in the transmit configuration field to
1095
   *  request an interrupt on every other transmitted packet.
1096
   *
1097
   *  NOTE: sonic_allocate() zeroes all of the memory allocated.
1098
   */
1099
 
1100
  sc->tdaTail = sonic_allocate(sc->tdaCount * sizeof *tdp);
1101
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
1102
  printf( "tdaTail = %p\n", sc->tdaTail );
1103
#endif
1104
  tdp = sc->tdaTail;
1105
  for (i = 0 ; i < sc->tdaCount ; i++) {
1106
    /*
1107
     *  Start off with the table of outstanding mbuf's
1108
     */
1109
 
1110
    /*
1111
     *  status, pkt_config, pkt_size, and all fragment fields
1112
     *  are set to zero by sonic_allocate.
1113
     */
1114
 
1115
/* XXX not used by the BSD drivers
1116
    tdp->frag[0].frag_link = LSW(tdp + 1);
1117
*/
1118
    if (i & 3)
1119
      tdp->pkt_config = TDA_CONFIG_PINT;
1120
 
1121
    tdp->status         = 0;
1122
    tdp->frag_count     = 0;
1123
    tdp->link_pad       = LSW(tdp + 1) | TDA_LINK_EOL;
1124
    tdp->linkp          = &((tdp + 1)->frag[0].frag_link);
1125
    tdp->next           = (TransmitDescriptor_t *)(tdp + 1);
1126
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS)
1127
    sonic_print_tx_descriptor( tdp );
1128
#endif
1129
    tdp++;
1130
  }
1131
  tdp--;
1132
  sc->tdaHead = tdp;
1133
  tdp->link_pad = LSW(sc->tdaTail) | TDA_LINK_EOL;
1134
  tdp->next = (TransmitDescriptor_t *)sc->tdaTail;
1135
  tdp->linkp = &sc->tdaTail->frag[0].frag_link;
1136
 
1137
  /*
1138
   *  Set up circular linked list in Receive Descriptor Area.
1139
   *  Leaves sc->rda pointing at the `beginning' of the list.
1140
   *
1141
   *  NOTE: The RDA and CDP must have the same MSW for their addresses.
1142
   */
1143
 
1144
  sc->rda = sonic_allocate(
1145
              (sc->rdaCount * sizeof(ReceiveDescriptor_t)) +
1146
                sizeof(CamDescriptor_t) );
1147
  sc->cdp = (CamDescriptorPointer_t) ((unsigned char *)sc->rda +
1148
        (sc->rdaCount * sizeof(ReceiveDescriptor_t)));
1149
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
1150
  printf( "rda area = %p\n", sc->rda );
1151
  printf( "cdp area = %p\n", sc->cdp );
1152
#endif
1153
 
1154
  ordp = rdp = sc->rda;
1155
  for (i = 0 ; i < sc->rdaCount ; i++) {
1156
    /*
1157
     *  status, byte_count, pkt_ptr0, pkt_ptr1, and seq_no are set
1158
     *  to zero by sonic_allocate.
1159
     */
1160
    rdp->link   = LSW(rdp + 1);
1161
    rdp->in_use = RDA_FREE;
1162
    rdp->next   = (ReceiveDescriptor_t *)(rdp + 1);
1163
    ordp = rdp;
1164
    rdp++;
1165
  }
1166
  /*
1167
   *  Link the last desriptor to the 1st one and mark it as the end
1168
   *  of the list.
1169
   */
1170
  ordp->next   = sc->rda;
1171
  ordp->link   = LSW(sc->rda) | RDA_LINK_EOL;
1172
  sc->rdp_last = ordp;
1173
 
1174
  /*
1175
   * Allocate the receive resource area.
1176
   * In accordance with National Application Note 746, make the
1177
   * receive resource area bigger than the receive descriptor area.
1178
   * This has the useful side effect of making the receive resource
1179
   * area big enough to hold the CAM descriptor area.
1180
   */
1181
 
1182
  sc->rsa = sonic_allocate((sc->rdaCount + RRA_EXTRA_COUNT) * sizeof *sc->rsa);
1183
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
1184
  printf( "rsa area = %p\n", sc->rsa );
1185
#endif
1186
 
1187
  /*
1188
   *  Set up list in Receive Resource Area.
1189
   *  Allocate space for incoming packets.
1190
   */
1191
 
1192
  rwp = sc->rsa;
1193
  for (i = 0 ; i < (sc->rdaCount + RRA_EXTRA_COUNT) ; i++, rwp++) {
1194
 
1195
    /*
1196
     * Allocate memory for buffer.
1197
     * Place a pointer to the mbuf at the beginning of the buffer
1198
     * so we can find the mbuf when the SONIC returns the buffer
1199
     * to the driver.
1200
     */
1201
 
1202
    MGETHDR (m, M_WAIT, MT_DATA);
1203
    MCLGET (m, M_WAIT);
1204
    m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
1205
    sc->rda[i].mbufp = m;
1206
 
1207
    p = mtod (m, void *);
1208
 
1209
    /*
1210
     * Set up RRA entry
1211
     */
1212
    rwp->buff_ptr_lsw = LSW(p);
1213
    rwp->buff_ptr_msw = MSW(p);
1214
    rwp->buff_wc_lsw = RBUF_WC;
1215
    rwp->buff_wc_msw = 0;
1216
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS)
1217
    sonic_print_rx_descriptor( &sc->rda[i] );
1218
#endif
1219
  }
1220
  sc->rea = rwp;
1221
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
1222
  printf( "rea area = %p\n", sc->rea );
1223
#endif
1224
 
1225
 
1226
  /*
1227
   * Issue a software reset.
1228
   */
1229
  (*sc->write_register)( rp, SONIC_REG_CR, CR_RST | CR_STP | CR_RXDIS | CR_HTX );
1230
 
1231
  /*
1232
   * Set up data configuration registers.
1233
   */
1234
  (*sc->write_register)( rp, SONIC_REG_DCR, sc->dcr_value );
1235
  (*sc->write_register)( rp, SONIC_REG_DCR2, sc->dc2_value );
1236
 
1237
  (*sc->write_register)( rp, SONIC_REG_CR, CR_STP | CR_RXDIS | CR_HTX );
1238
 
1239
  /*
1240
   * Mask all interrupts
1241
   */
1242
  (*sc->write_register)( rp, SONIC_REG_IMR, 0x0 ); /* XXX was backwards */
1243
 
1244
  /*
1245
   * Clear outstanding interrupts.
1246
   */
1247
  (*sc->write_register)( rp, SONIC_REG_ISR, 0x7FFF );
1248
 
1249
  /*
1250
   *  Clear the tally counters
1251
   */
1252
 
1253
  (*sc->write_register)( rp, SONIC_REG_CRCT, 0xFFFF );
1254
  (*sc->write_register)( rp, SONIC_REG_FAET, 0xFFFF );
1255
  (*sc->write_register)( rp, SONIC_REG_MPT, 0xFFFF );
1256
  (*sc->write_register)( rp, SONIC_REG_RSC, 0 );
1257
 
1258
  /*
1259
   *  Set the Receiver mode
1260
   *
1261
   *  Enable/disable reception of broadcast packets
1262
   */
1263
 
1264
  if (sc->acceptBroadcast)
1265
    (*sc->write_register)( rp, SONIC_REG_RCR, RCR_BRD );
1266
  else
1267
    (*sc->write_register)( rp, SONIC_REG_RCR, 0 );
1268
 
1269
  /*
1270
   * Set up Resource Area pointers
1271
   */
1272
 
1273
  (*sc->write_register)( rp, SONIC_REG_URRA, MSW(sc->rsa) );
1274
  (*sc->write_register)( rp, SONIC_REG_RSA, LSW(sc->rsa) );
1275
 
1276
  (*sc->write_register)( rp, SONIC_REG_REA, LSW(sc->rea) );
1277
 
1278
  (*sc->write_register)( rp, SONIC_REG_RRP, LSW(sc->rsa) );
1279
  (*sc->write_register)( rp, SONIC_REG_RWP, LSW(sc->rsa) ); /* XXX was rea */
1280
 
1281
  (*sc->write_register)( rp, SONIC_REG_URDA, MSW(sc->rda) );
1282
  (*sc->write_register)( rp, SONIC_REG_CRDA, LSW(sc->rda) );
1283
 
1284
  (*sc->write_register)( rp, SONIC_REG_UTDA, MSW(sc->tdaTail) );
1285
  (*sc->write_register)( rp, SONIC_REG_CTDA, LSW(sc->tdaTail) );
1286
 
1287
  /*
1288
   * Set End Of Buffer Count register to the value recommended
1289
   * in Note 1 of Section 3.4.4.4 of the SONIC data sheet.
1290
   */
1291
 
1292
  (*sc->write_register)( rp, SONIC_REG_EOBC, RBUF_WC - 2 );
1293
 
1294
  /*
1295
   *  Issue the load RRA command
1296
   */
1297
 
1298
  (*sc->write_register)( rp, SONIC_REG_CR, CR_RRRA );
1299
  while ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_RRRA)
1300
    continue;
1301
 
1302
  /*
1303
   * Remove device reset
1304
   */
1305
 
1306
  (*sc->write_register)( rp, SONIC_REG_CR, 0 );
1307
 
1308
  /*
1309
   *  Set up the SONIC CAM with our hardware address.
1310
   */
1311
 
1312
  hwaddr = sc->arpcom.ac_enaddr;
1313
  cdp = sc->cdp;
1314
 
1315
#if (SONIC_DEBUG & SONIC_DEBUG_CAM)
1316
  printf( "hwaddr: %2x:%2x:%2x:%2x:%2x:%2x\n",
1317
     hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5] );
1318
#endif
1319
 
1320
  cdp->cep  = 0;                     /* Fill first and only entry in CAM */
1321
  cdp->cap0 = hwaddr[1] << 8 | hwaddr[0];
1322
  cdp->cap1 = hwaddr[3] << 8 | hwaddr[2];
1323
  cdp->cap2 = hwaddr[5] << 8 | hwaddr[4];
1324
  cdp->ce   = 0x0001;                /* Enable first entry in CAM */
1325
 
1326
  (*sc->write_register)( rp, SONIC_REG_CDC, 1 );      /* 1 entry in CDA */
1327
  (*sc->write_register)( rp, SONIC_REG_CDP, LSW(cdp) );
1328
  (*sc->write_register)( rp, SONIC_REG_CR,  CR_LCAM );  /* Load the CAM */
1329
 
1330
  while ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_LCAM)
1331
    continue;
1332
 
1333
  /*
1334
   * Verify that CAM was properly loaded.
1335
   */
1336
 
1337
  (*sc->write_register)( rp, SONIC_REG_CR, CR_RST | CR_STP | CR_RXDIS | CR_HTX );
1338
 
1339
#if (SONIC_DEBUG & SONIC_DEBUG_CAM)
1340
  (*sc->write_register)( rp, SONIC_REG_CEP, 0 );  /* Select first entry in CAM */
1341
    printf ("Loaded Ethernet address into SONIC CAM.\n"
1342
      "  Wrote %04x%04x%04x - %#x\n"
1343
      "   Read %04x%04x%04x - %#x\n",
1344
        cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce,
1345
        (*sc->read_register)( rp, SONIC_REG_CAP2 ),
1346
        (*sc->read_register)( rp, SONIC_REG_CAP1 ),
1347
        (*sc->read_register)( rp, SONIC_REG_CAP0 ),
1348
        (*sc->read_register)( rp, SONIC_REG_CE ));
1349
 
1350
  (*sc->write_register)( rp, SONIC_REG_CEP, 0 );  /* Select first entry in CAM */
1351
  if (((*sc->read_register)( rp, SONIC_REG_CAP2 ) != cdp->cap2)
1352
   || ((*sc->read_register)( rp, SONIC_REG_CAP1 ) != cdp->cap1)
1353
   || ((*sc->read_register)( rp, SONIC_REG_CAP0 ) != cdp->cap0)
1354
   || ((*sc->read_register)( rp, SONIC_REG_CE ) != cdp->ce)) {
1355
    printf ("Failed to load Ethernet address into SONIC CAM.\n"
1356
      "  Wrote %04x%04x%04x - %#x\n"
1357
      "   Read %04x%04x%04x - %#x\n",
1358
        cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce,
1359
        (*sc->read_register)( rp, SONIC_REG_CAP2 ),
1360
        (*sc->read_register)( rp, SONIC_REG_CAP1 ),
1361
        (*sc->read_register)( rp, SONIC_REG_CAP0 ),
1362
        (*sc->read_register)( rp, SONIC_REG_CE ));
1363
    rtems_panic ("SONIC LCAM");
1364
  }
1365
#endif
1366
 
1367
  (*sc->write_register)(rp, SONIC_REG_CR, /* CR_TXP | */CR_RXEN | CR_STP);
1368
 
1369
  /*
1370
   * Attach SONIC interrupt handler
1371
   */
1372
/* XXX
1373
  (*sc->write_register)( rp, SONIC_REG_IMR, 0 );
1374
*/
1375
  old_handler = set_vector(sonic_interrupt_handler, sc->vector, 1);
1376
 
1377
  /*
1378
   * Remainder of hardware initialization is
1379
   * done by the receive and transmit daemons.
1380
   */
1381
}
1382
 
1383
/*
1384
 * Send packet (caller provides header).
1385
 */
1386
 
1387
SONIC_STATIC void sonic_start(struct ifnet *ifp)
1388
{
1389
  struct sonic_softc *sc = ifp->if_softc;
1390
 
1391
  rtems_event_send(sc->txDaemonTid, START_TRANSMIT_EVENT);
1392
  ifp->if_flags |= IFF_OACTIVE;
1393
}
1394
 
1395
/*
1396
 * Initialize and start the device
1397
 */
1398
 
1399
SONIC_STATIC void sonic_init (void *arg)
1400
{
1401
  struct sonic_softc *sc = arg;
1402
  struct ifnet *ifp = &sc->arpcom.ac_if;
1403
  void *rp = sc->sonic;
1404
  int rcr;
1405
 
1406
  if (sc->txDaemonTid == 0) {
1407
 
1408
    /*
1409
     * Set up SONIC hardware
1410
     */
1411
    sonic_initialize_hardware (sc);
1412
 
1413
    /*
1414
     * Start driver tasks
1415
     */
1416
    sc->rxDaemonTid = rtems_bsdnet_newproc ("SNrx", 4096, sonic_rxDaemon, sc);
1417
    sc->txDaemonTid = rtems_bsdnet_newproc ("SNtx", 4096, sonic_txDaemon, sc);
1418
  }
1419
 
1420
  /*
1421
   * Set flags appropriately
1422
   */
1423
  rcr = (*sc->read_register)( rp, SONIC_REG_RCR );
1424
  if (ifp->if_flags & IFF_PROMISC)
1425
    rcr |= RCR_PRO;
1426
  else
1427
    rcr &= ~RCR_PRO;
1428
  (*sc->write_register)( rp, SONIC_REG_RCR, rcr);
1429
 
1430
  /*
1431
   * Tell the world that we're running.
1432
   */
1433
  ifp->if_flags |= IFF_RUNNING;
1434
 
1435
  /*
1436
   * Enable receiver and transmitter
1437
   */
1438
  sonic_enable_interrupts( sc, IMR_TXEREN | (IMR_PRXEN | IMR_RBAEEN) );
1439
  sonic_command( sc, CR_RXEN );
1440
}
1441
 
1442
/*
1443
 * Driver ioctl handler
1444
 */
1445
static int
1446
sonic_ioctl (struct ifnet *ifp, int command, caddr_t data)
1447
{
1448
  struct sonic_softc *sc = ifp->if_softc;
1449
  int error = 0;
1450
 
1451
  switch (command) {
1452
    case SIOCGIFADDR:
1453
    case SIOCSIFADDR:
1454
      ether_ioctl (ifp, command, data);
1455
      break;
1456
 
1457
    case SIOCSIFFLAGS:
1458
      switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
1459
        case IFF_RUNNING:
1460
          sonic_stop (sc);
1461
          break;
1462
 
1463
        case IFF_UP:
1464
          sonic_init (sc);
1465
          break;
1466
 
1467
        case IFF_UP | IFF_RUNNING:
1468
          sonic_stop (sc);
1469
          sonic_init (sc);
1470
          break;
1471
 
1472
        default:
1473
          break;
1474
        }
1475
      break;
1476
 
1477
    case SIO_RTEMS_SHOW_STATS:
1478
      sonic_stats (sc);
1479
      break;
1480
 
1481
    /*
1482
     * FIXME: All sorts of multicast commands need to be added here!
1483
     */
1484
    default:
1485
      error = EINVAL;
1486
      break;
1487
  }
1488
  return error;
1489
}
1490
 
1491
/*
1492
 * Attach an SONIC driver to the system
1493
 * This is the only `extern' function in the driver.
1494
 */
1495
 
1496
int
1497
rtems_sonic_driver_attach (
1498
  struct rtems_bsdnet_ifconfig *config,
1499
  sonic_configuration_t *chip
1500
)
1501
{
1502
  struct sonic_softc *sc;
1503
  struct ifnet *ifp;
1504
  int mtu;
1505
  int unitNumber;
1506
  char *unitName;
1507
 
1508
  /*
1509
   * Parse driver name
1510
   */
1511
  if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0)
1512
    return 0;
1513
 
1514
  /*
1515
   * Is driver free?
1516
   */
1517
  if ((unitNumber <= 0) || (unitNumber > NSONIC)) {
1518
    printf ("Bad SONIC unit number.\n");
1519
     return 0;
1520
  }
1521
  sc = &sonic_softc[unitNumber - 1];
1522
  ifp = &sc->arpcom.ac_if;
1523
  if (ifp->if_softc != NULL) {
1524
    printf ("Driver already in use.\n");
1525
    return 0;
1526
  }
1527
 
1528
  /*
1529
   *  zero out the control structure
1530
   */
1531
 
1532
  memset( sc, 0, sizeof(*sc) );
1533
 
1534
 
1535
  /*
1536
   * Process options
1537
   */
1538
  if (config->hardware_address) {
1539
    memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
1540
  }
1541
  else {
1542
    memset (sc->arpcom.ac_enaddr, 0x08, ETHER_ADDR_LEN);
1543
  }
1544
  if (config->mtu)
1545
    mtu = config->mtu;
1546
  else
1547
    mtu = ETHERMTU;
1548
  if (config->rbuf_count)
1549
    sc->rdaCount = config->rbuf_count;
1550
  else
1551
    sc->rdaCount = chip->rda_count;
1552
  if (config->xbuf_count)
1553
    sc->tdaCount = config->xbuf_count;
1554
  else
1555
    sc->tdaCount = chip->tda_count;
1556
  sc->acceptBroadcast = !config->ignore_broadcast;
1557
 
1558
  sc->sonic = (void *) chip->base_address;
1559
  sc->vector = chip->vector;
1560
  sc->dcr_value = chip->dcr_value;
1561
  sc->dc2_value  = chip->dc2_value;
1562
  sc->write_register = chip->write_register;
1563
  sc->read_register  = chip->read_register;
1564
 
1565
  /*
1566
   * Set up network interface values
1567
   */
1568
  ifp->if_softc = sc;
1569
  ifp->if_unit = unitNumber;
1570
  ifp->if_name = unitName;
1571
  ifp->if_mtu = mtu;
1572
  ifp->if_init = sonic_init;
1573
  ifp->if_ioctl = sonic_ioctl;
1574
  ifp->if_start = sonic_start;
1575
  ifp->if_output = ether_output;
1576
  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
1577
  if (ifp->if_snd.ifq_maxlen == 0)
1578
    ifp->if_snd.ifq_maxlen = ifqmaxlen;
1579
 
1580
  /*
1581
   * Attach the interface
1582
   */
1583
  if_attach (ifp);
1584
  ether_ifattach (ifp);
1585
  return 1;
1586
}
1587
 
1588
#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS)
1589
#include <stdio.h>
1590
 
1591
char SONIC_Reg_name[64][6]= {
1592
    "CR",         /* 0x00 */
1593
    "DCR",        /* 0x01 */
1594
    "RCR",        /* 0x02 */
1595
    "TCR",        /* 0x03 */
1596
    "IMR",        /* 0x04 */
1597
    "ISR",        /* 0x05 */
1598
    "UTDA",       /* 0x06 */
1599
    "CTDA",       /* 0x07 */
1600
    "0x08",       /* 0x08 */
1601
    "0x09",       /* 0x09 */
1602
    "0x0A",       /* 0x0A */
1603
    "0x0B",       /* 0x0B */
1604
    "0x0C",       /* 0x0C */
1605
    "URDA",       /* 0x0D */
1606
    "CRDA",       /* 0x0E */
1607
    "0x0F",       /* 0x0F */
1608
    "0x10",       /* 0x10 */
1609
    "0x11",       /* 0x11 */
1610
    "0x12",       /* 0x12 */
1611
    "EOBC",       /* 0x13 */
1612
    "URRA",       /* 0x14 */
1613
    "RSA",        /* 0x15 */
1614
    "REA",        /* 0x16 */
1615
    "RRP",        /* 0x17 */
1616
    "RWP",        /* 0x18 */
1617
    "0x19",       /* 0x19 */
1618
    "0x1A",       /* 0x1A */
1619
    "0x1B",       /* 0x1B */
1620
    "0x1C",       /* 0x1C */
1621
    "0x0D",       /* 0x1D */
1622
    "0x1E",       /* 0x1E */
1623
    "0x1F",       /* 0x1F */
1624
    "0x20",       /* 0x20 */
1625
    "CEP",        /* 0x21 */
1626
    "CAP2",       /* 0x22 */
1627
    "CAP1",       /* 0x23 */
1628
    "CAP0",       /* 0x24 */
1629
    "CE",         /* 0x25 */
1630
    "CDP",        /* 0x26 */
1631
    "CDC",        /* 0x27 */
1632
    "SR",         /* 0x28 */
1633
    "WT0",        /* 0x29 */
1634
    "WT1",        /* 0x2A */
1635
    "RSC",        /* 0x2B */
1636
    "CRCT",       /* 0x2C */
1637
    "FAET",       /* 0x2D */
1638
    "MPT",        /* 0x2E */
1639
    "MDT",        /* 0x2F */
1640
    "0x30",       /* 0x30 */
1641
    "0x31",       /* 0x31 */
1642
    "0x32",       /* 0x32 */
1643
    "0x33",       /* 0x33 */
1644
    "0x34",       /* 0x34 */
1645
    "0x35",       /* 0x35 */
1646
    "0x36",       /* 0x36 */
1647
    "0x37",       /* 0x37 */
1648
    "0x38",       /* 0x38 */
1649
    "0x39",       /* 0x39 */
1650
    "0x3A",       /* 0x3A */
1651
    "0x3B",       /* 0x3B */
1652
    "0x3C",       /* 0x3C */
1653
    "0x3D",       /* 0x3D */
1654
    "0x3E",       /* 0x3E */
1655
    "DCR2"        /* 0x3F */
1656
};
1657
#endif

powered by: WebSVN 2.1.0

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