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

4.104.114.84.95
Last change on this file since c9c67390 was c9c67390, checked in by Joel Sherrill <joel.sherrill@…>, on 02/05/99 at 00:34:17

Split SONIC chip into appropriate files for libchip'ing. The portable
portion is now in the libchip tree and the dmv177 configuration is in
the dmv177 bsp. The performance impact of libchip'ing this driver
was minimal.

  • 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, 0);
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.