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

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

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

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