source: rtems/c/src/lib/libchip/network/sonic.c @ b6f5f93

4.104.114.84.95
Last change on this file since b6f5f93 was e602b3f, checked in by Joel Sherrill <joel.sherrill@…>, on 03/11/99 at 22:13:45

Interrupt handler installed as raw handler. Problem caught by
by Jiri Gaisler <jgais@…> when using this
driver on a SPARC.

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