source: rtems/bsps/shared/net/sonic.c @ 762fa62

5
Last change on this file since 762fa62 was 27de4e1f, checked in by Sebastian Huber <sebastian.huber@…>, on 04/03/18 at 05:20:11

bsps: Move libchip to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

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