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

4.104.114.84.95
Last change on this file since 7397638 was 7397638, checked in by Joel Sherrill <joel.sherrill@…>, on 02/04/99 at 22:59:46

Works great now.

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