source: rtems/c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.c @ d93b23d

4.104.114.84.95
Last change on this file since d93b23d was 7dbab720, checked in by Joel Sherrill <joel.sherrill@…>, on 01/31/99 at 20:46:52

Can send and receive packets but fails when TDA wraps. There appears
to be a problem with overwriting the TX descriptors during an RX.

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