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

4.104.114.84.95
Last change on this file since 811115de was 811115de, checked in by Joel Sherrill <joel.sherrill@…>, on 02/02/99 at 16:28:42

Added debug print routines for TX and RX descriptors.

Fixed bug where only the mbuf associated with the first TX fragment was
being freed.

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