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

4.104.114.84.95
Last change on this file since 13cc89e1 was 13cc89e1, checked in by Joel Sherrill <joel.sherrill@…>, on 02/04/99 at 23:45:55

Reorganized into libchip style but not yet split out into multiple files
and placed in the right shareable directories.

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