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

4.104.114.84.95
Last change on this file since f3e13a1e was f3e13a1e, checked in by Joel Sherrill <joel.sherrill@…>, on 10/26/98 at 23:31:02

Merged base line score603e BSP

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