source: rtems/c/src/libchip/network/sonic.c @ f010a5e

4.104.114.84.95
Last change on this file since f010a5e was f010a5e, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 2, 2001 at 6:17:22 PM

2001-03-01 Joel Sherrill <joel@…>

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