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

4.104.114.84.95
Last change on this file since 7fc5d54e was 7fc5d54e, checked in by Joel Sherrill <joel.sherrill@…>, on 08/03/98 at 21:01:21

Switched to read/write register routines and added some basic debug
help.

  • Property mode set to 100644
File size: 34.6 KB
Line 
1#define SONIC_DEBUG
2/*
3 *******************************************************************
4 *******************************************************************
5 **                                                               **
6 **         RTEMS/KA9Q DRIVER FOR NATIONAL DP83932 `SONIC'        **
7 **         SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER         **
8 **                                                               **
9 *******************************************************************
10 *******************************************************************
11 */
12
13/*
14 * $Revision$   $Date$   $Author$
15 * $State$
16 */
17
18/*
19 * References:
20 * 1) DP83932C-20/25/33 MHz SONIC(TM) Systems-Oriented Network Interface
21 *    Controller data sheet.  TL/F/10492, RRD-B30M105, National Semiconductor,
22 *    1995.
23 *
24 * 2) Software Driver Programmer's Guide for the DP83932 SONIC(TM),
25 *    Application Note 746, Wesley Lee and Mike Lui, TL/F/11140,
26 *    RRD-B30M75, National Semiconductor, March, 1991.
27 *
28 * 3) SVME/DMV-171 Single Board Computer Documentation Package, #805905,
29 *    DY 4 Systems Inc., Kanata, Ontario, September, 1996.
30 */
31
32#include "sonic.h"
33
34#include <rtems/error.h>
35#include <ka9q/rtems_ka9q.h>
36#include <ka9q/global.h>
37#include <ka9q/domain.h>
38#include <ka9q/enet.h>
39#include <ka9q/iface.h>
40#include <ka9q/netuser.h>
41#include <ka9q/trace.h>
42#include <ka9q/commands.h>
43
44/*
45 * XXX
46 */
47
48#include <dmv170.h>
49
50/*
51 *  Use the top line if you want more symbols.
52 */
53
54#define SONIC_STATIC
55/* #define SONIC_STATIC static */
56
57/*
58 * Number of devices supported by this driver
59 */
60#ifndef NSONIC
61# define NSONIC 1
62#endif
63
64/*
65 * Default location of device registers
66 */
67#ifndef SONIC_BASE_ADDRESS
68# define SONIC_BASE_ADDRESS 0xF3000000
69# warning "Using default SONIC_BASE_ADDRESS."
70#endif
71
72/*
73 * Default interrupt vector
74 */
75#ifndef SONIC_VECTOR
76# define SONIC_VECTOR 1
77# warning "Using default SONIC_VECTOR."
78#endif
79
80/*
81 * Default device configuration register values
82 * Conservative, generic values.
83 * DCR:
84 *      No extended bus mode
85 *      Unlatched bus retry
86 *      Programmable outputs unused
87 *      Asynchronous bus mode
88 *      User definable pins unused
89 *      No wait states (access time controlled by DTACK*)
90 *      32-bit DMA
91 *      Empty/Fill DMA mode
92 *      Maximum Transmit/Receive FIFO
93 * DC2:
94 *      Extended programmable outputs unused
95 *      Normal HOLD request
96 *      Packet compress output unused
97 *      No reject on CAM match
98 */
99#define SONIC_DCR (DCR_DW | DCR_SBUS | DCR_TFT1 | DCR_TFT0)
100#ifndef SONIC_DCR
101# define SONIC_DCR (DCR_DW | DCR_TFT1 | DCR_TFT0)
102#endif
103#ifndef SONIC_DC2
104# define SONIC_DC2 (0)
105#endif
106
107/*
108 * Default sizes of transmit and receive descriptor areas
109 */
110#define RDA_COUNT     20
111#define TDA_COUNT     10
112
113/*
114 *
115 * As suggested by National Application Note 746, make the
116 * receive resource area bigger than the receive descriptor area.
117 */
118#define RRA_EXTRA_COUNT  3
119
120/*
121 * RTEMS event used by interrupt handler to signal daemons.
122 */
123#define INTERRUPT_EVENT  RTEMS_EVENT_1
124
125/*
126 * Largest Ethernet frame.
127 */
128#define MAXIMUM_FRAME_SIZE  1518
129
130/*
131 * Receive buffer size.
132 * Allow for a pointer, plus a full ethernet frame (including Frame
133 * Check Sequence) rounded up to a 4-byte boundary.
134 */
135#define RBUF_SIZE  ((sizeof (void *) + (MAXIMUM_FRAME_SIZE) + 3) & ~3)
136#define RBUF_WC    ((((MAXIMUM_FRAME_SIZE) + 3) & ~3) / 2)
137
138/*
139 * Macros for manipulating 32-bit pointers as 16-bit fragments
140 */
141#define LSW(p)   ((rtems_unsigned16)((rtems_unsigned32)(p)))
142#define MSW(p)   ((rtems_unsigned16)((rtems_unsigned32)(p) >> 16))
143#define PTR(m,l) ((void*)(((rtems_unsigned16)(m)<<16)|(rtems_unsigned16)(l)))
144
145/*
146 * Hardware-specific storage
147 */
148struct sonic {
149  /*
150   * Connection to KA9Q
151   */
152  struct iface                     *iface;
153
154  /*
155   * Default location of device registers
156   * ===CACHE===
157   * This area must be non-cacheable, guarded.
158   */
159  void                             *sonic;
160
161  /*
162   * Interrupt vector
163   */
164  rtems_vector_number             vector;
165
166  /*
167   * Task waiting for transmit resources
168   */
169  rtems_id                        txWaitTid;
170
171  /*
172   * Receive resource area
173   */
174  int                             rdaCount;
175  ReceiveResourcePointer_t        rsa;
176
177  /*
178   * Transmit descriptors
179   */
180  int        tdaCount;
181  TransmitDescriptorPointer_t     tdaHead;  /* Last filled */
182  TransmitDescriptorPointer_t     tdaTail;  /* Next to retire */
183  int                             tdaActiveCount;
184
185  /*
186   * Statistics
187   */
188  unsigned long                   rxInterrupts;
189  unsigned long                   rxMissed;
190  unsigned long                   rxGiant;
191  unsigned long                   rxNonOctet;
192  unsigned long                   rxBadCRC;
193  unsigned long                   rxCollision;
194
195  unsigned long                   txInterrupts;
196  unsigned long                   txSingleCollision;
197  unsigned long                   txMultipleCollision;
198  unsigned long                   txCollision;
199  unsigned long                   txDeferred;
200  unsigned long                   txUnderrun;
201  unsigned long                   txLateCollision;
202  unsigned long                   txExcessiveCollision;
203  unsigned long                   txExcessiveDeferral;
204  unsigned long                   txLostCarrier;
205  unsigned long                   txRawWait;
206};
207SONIC_STATIC struct sonic sonic[NSONIC];
208
209/*
210 ******************************************************************
211 *                                                                *
212 *                        Support Routines                        *
213 *                                                                *
214 ******************************************************************
215 */
216
217void sonic_write_register(
218  void       *base,
219  unsigned32  regno,
220  unsigned32  value
221);
222
223unsigned32 sonic_read_register(
224  void       *base,
225  unsigned32  regno
226);
227
228/*
229 * Allocate non-cacheable memory on a single 64k page.
230 * Very simple minded -- just keeps trying till the memory is on a single page.
231 */
232SONIC_STATIC void * sonic_allocate (unsigned int nbytes)
233{
234  void *p;
235  unsigned long a1, a2;
236
237  for (;;) {
238    /*
239     * ===CACHE===
240     * Change malloc to malloc_noncacheable_guarded.
241     */
242    p = malloc (nbytes);
243    if (p == NULL)
244      rtems_panic ("No memory!");
245    a1 = (unsigned long)p;
246    a2 = a1 + nbytes - 1;
247    if ((a1 >> 16) == (a2 >> 16))
248      break;
249  }
250  return p;
251}
252
253/*
254 * Shut down the interface.
255 * This is a pretty simple-minded routine.  It doesn't worry
256 * about cleaning up mbufs, shutting down daemons, etc.
257 */
258
259SONIC_STATIC int sonic_stop (struct iface *iface)
260{
261  int i;
262  struct sonic *dp = &sonic[iface->dev];
263  void *rp = dp->sonic;
264
265  /*
266   * Stop the transmitter and receiver.
267   */
268  sonic_write_register( rp, SONIC_REG_CR, CR_HTX | CR_RXDIS );
269
270  /*
271   * Wait for things to stop.
272   * For safety's sake, there is an alternate exit.
273   */
274  i = 0;
275  while (sonic_read_register( rp, SONIC_REG_CR ) & (CR_RXEN | CR_TXP)) {
276    if (++i == 10000)
277      break;
278  }
279
280  /*
281   * Reset the device
282   */
283  sonic_write_register( rp, SONIC_REG_CR, CR_RST );
284  sonic_write_register( rp, SONIC_REG_IMR, 0 );
285  return 0;
286}
287
288/*
289 * Show interface statistics
290 */
291
292SONIC_STATIC void sonic_show (struct iface *iface)
293{
294  struct sonic *dp = &sonic[iface->dev];
295
296  printf ("    Rx Interrupts:%-8lu", dp->rxInterrupts);
297  printf ("            Giant:%-8lu", dp->rxGiant);
298  printf ("        Non-octet:%-8lu\n", dp->rxNonOctet);
299  printf ("          Bad CRC:%-8lu", dp->rxBadCRC);
300  printf ("        Collision:%-8lu", dp->rxCollision);
301  printf ("           Missed:%-8lu\n", dp->rxMissed);
302
303  printf (    "    Tx Interrupts:%-8lu", dp->txInterrupts);
304  printf (  "           Deferred:%-8lu", dp->txDeferred);
305  printf ("        Lost Carrier:%-8lu\n", dp->txLostCarrier);
306  printf (   "Single Collisions:%-8lu", dp->txSingleCollision);
307  printf ( "Multiple Collisions:%-8lu", dp->txMultipleCollision);
308  printf ("Excessive Collisions:%-8lu\n", dp->txExcessiveCollision);
309  printf (   " Total Collisions:%-8lu", dp->txCollision);
310  printf ( "     Late Collision:%-8lu", dp->txLateCollision);
311  printf ("            Underrun:%-8lu\n", dp->txUnderrun);
312  printf (   "  Raw output wait:%-8lu\n", dp->txRawWait);
313}
314
315/*
316 ******************************************************************
317 *                                                                *
318 *                        Interrupt Handler                       *
319 *                                                                *
320 ******************************************************************
321 */
322
323SONIC_STATIC rtems_isr sonic_interrupt_handler (rtems_vector_number v)
324{
325  struct sonic *dp = sonic;
326  void *rp;
327
328#if (NSONIC > 1)
329  /*
330   * Find the device which requires service
331   */
332  for (;;) {
333    if (dp->vector == v)
334      break;
335    if (++dp == &sonic[NSONIC])
336      return;  /* Spurious interrupt? */
337  }
338#endif /* NSONIC > 1 */
339
340  /*
341   * Get pointer to SONIC registers
342   */
343  rp = dp->sonic;
344
345  /*
346   * Packet received or receive buffer area exceeded?
347   */
348  if ((sonic_read_register( rp, SONIC_REG_IMR ) & (IMR_PRXEN | IMR_RBAEEN)) &&
349      (sonic_read_register( rp, SONIC_REG_ISR ) & (ISR_PKTRX | ISR_RBAE))) {
350    sonic_write_register(
351       rp,
352       SONIC_REG_IMR,
353       sonic_read_register( rp, SONIC_REG_IMR) & ~(IMR_PRXEN | IMR_RBAEEN)
354    );
355    dp->rxInterrupts++;
356    rtems_event_send (dp->iface->rxproc, INTERRUPT_EVENT);
357  }
358
359  /*
360   * Packet started, transmitter done or transmitter error?
361   */
362  if ((sonic_read_register( rp, SONIC_REG_IMR ) & (IMR_PINTEN | IMR_PTXEN | IMR_TXEREN))
363   && (sonic_read_register( rp, SONIC_REG_ISR ) & (ISR_PINT | ISR_TXDN | ISR_TXER))) {
364    sonic_write_register(
365       rp,
366       SONIC_REG_IMR,
367       sonic_read_register( rp, SONIC_REG_IMR) &
368                  ~(IMR_PINTEN | IMR_PTXEN | IMR_TXEREN)
369    );
370    dp->rxInterrupts++;
371    dp->txInterrupts++;
372    rtems_event_send (dp->txWaitTid, INTERRUPT_EVENT);
373  }
374}
375
376/*
377 ******************************************************************
378 *                                                                *
379 *                      Transmitter Routines                      *
380 *                                                                *
381 ******************************************************************
382 */
383
384/*
385 * Soak up transmit descriptors that have been sent.
386 */
387
388SONIC_STATIC void sonic_retire_tda (struct sonic *dp)
389{
390  rtems_unsigned16 status;
391  unsigned int collisions;
392
393  /*
394   * Repeat for all completed transmit descriptors.
395   */
396  while ((dp->tdaActiveCount != 0)
397      && ((status = dp->tdaTail->status) != 0)) {
398    /*
399     * Check for errors which stop the transmitter.
400     */
401    if (status & (TDA_STATUS_EXD |
402        TDA_STATUS_EXC |
403        TDA_STATUS_FU |
404        TDA_STATUS_BCM)) {
405      /*
406       * Restart the transmitter if there are
407       * packets waiting to go.
408       */
409      rtems_unsigned16 link;
410      link = *(dp->tdaTail->linkp);
411
412      if ((link & TDA_LINK_EOL) == 0) {
413        void *rp = dp->sonic;
414
415        sonic_write_register( rp, SONIC_REG_CTDA, link );
416        sonic_write_register( rp, SONIC_REG_CR, CR_TXP );
417      }
418    }
419
420    /*
421     * Update network statistics
422     */
423    collisions = (status & TDA_STATUS_COLLISION_MASK) >> TDA_STATUS_COLLISION_SHIFT;
424    if (collisions) {
425      if (collisions == 1)
426        dp->txSingleCollision++;
427      else
428        dp->txMultipleCollision++;
429      dp->txCollision += collisions;
430    }
431    if (status & TDA_STATUS_EXC)
432      dp->txExcessiveCollision++;
433    if (status & TDA_STATUS_OWC)
434      dp->txLateCollision++;
435    if (status & TDA_STATUS_EXD)
436      dp->txExcessiveDeferral++;
437    if (status & TDA_STATUS_DEF)
438      dp->txDeferred++;
439    if (status & TDA_STATUS_FU)
440      dp->txUnderrun++;
441    if (status & TDA_STATUS_CRSL)
442      dp->txLostCarrier++;
443
444    /*
445     * Free the packet
446     */
447    dp->tdaActiveCount--;
448    free_p ((struct mbuf **)&dp->tdaTail->mbufp);
449
450    /*
451     * Move to the next transmit descriptor
452     */
453    dp->tdaTail = dp->tdaTail->next;
454  }
455}
456
457/*
458 * Send raw packet (caller provides header).
459 * This code runs in the context of the interface transmit
460 * task (most packets)  or in the context of the network
461 * task (for ARP requests).
462 */
463
464SONIC_STATIC int sonic_raw (struct iface *iface, struct mbuf **bpp)
465{
466  struct sonic *dp = &sonic[iface->dev];
467  void *rp = dp->sonic;
468  struct mbuf *bp;
469  TransmitDescriptorPointer_t tdp;
470  volatile struct TransmitDescriptorFragLink *fp;
471  unsigned int packetSize;
472  int i;
473  static char padBuf[64];
474
475  /*
476   * Update the log.
477   */
478  iface->rawsndcnt++;
479  iface->lastsent = secclock ();
480  dump (iface, IF_TRACE_OUT, *bpp);
481
482  /*
483   * It would not do to have two tasks active in the transmit
484   * loop at the same time.
485   * The blocking is simple-minded since the odds of two tasks
486   * simultaneously attempting to use this code are low.  The only
487   * way that two tasks can try to run here is:
488   *  1) Task A enters this code and ends up having to
489   *     wait for a transmit buffer descriptor.
490   *  2) Task B gains control and tries to transmit a packet.
491   * The RTEMS/KA9Q scheduling semaphore ensures that there
492   * are no race conditions associated with manipulating the
493   * txWaitTid variable.
494   */
495  if (dp->txWaitTid) {
496    dp->txRawWait++;
497    while (dp->txWaitTid)
498      rtems_ka9q_ppause (10);
499  }
500
501  /*
502   * Free up transmit descriptors.
503   */
504  sonic_retire_tda (dp);
505
506  /*
507   * Wait for transmit descriptor to become available.
508   */
509  if (dp->tdaActiveCount == dp->tdaCount) {
510    /*
511     * Find out who we are
512     */
513    if (dp->txWaitTid == 0)
514      rtems_task_ident (RTEMS_SELF, 0, &dp->txWaitTid);
515
516    /*
517     * Clear old events.
518     */
519    sonic_write_register( rp, SONIC_REG_ISR, ISR_PINT | ISR_TXDN | ISR_TXER );
520
521    /*
522     * Wait for transmit descriptor to become available.
523     * Note that the transmit descriptors are checked
524     * *before* * entering the wait loop -- this catches
525     * the possibility that a transmit descriptor became
526     * available between the `if' the started this block,
527     * and the clearing of the interrupt status register.
528     */
529    sonic_retire_tda (dp);
530    while (dp->tdaActiveCount == dp->tdaCount) {
531      /*
532       * Enable transmitter interrupts.
533       */
534      sonic_write_register(
535         rp,
536         SONIC_REG_IMR,
537         sonic_read_register( rp, SONIC_REG_IMR) |
538                (IMR_PINTEN | IMR_PTXEN | IMR_TXEREN)
539      );
540
541      /*
542       * Wait for interrupt
543       */
544      rtems_ka9q_event_receive (INTERRUPT_EVENT,
545            RTEMS_WAIT|RTEMS_EVENT_ANY,
546            RTEMS_NO_TIMEOUT);
547      sonic_write_register( rp, SONIC_REG_ISR, ISR_PINT | ISR_TXDN | ISR_TXER );
548      sonic_retire_tda (dp);
549    }
550  }
551
552  /*
553   * Get the head of the packet mbuf chain.
554   */
555  bp = *bpp;
556
557  /*
558   * Fill in the transmit descriptor fragment descriptors.
559   * ===CACHE===
560   * If data cache is operating in write-back mode, flush cached
561   * data to memory.
562   */
563  tdp = dp->tdaHead->next;
564  tdp->mbufp = bp;
565  packetSize = 0;
566  fp = tdp->frag;
567  for (i = 0 ; i < MAXIMUM_FRAGS_PER_DESCRIPTOR ; i++, fp++) {
568    fp->frag_lsw = LSW(bp->data);
569    fp->frag_msw = MSW(bp->data);
570    fp->frag_size = bp->cnt;
571    packetSize += bp->cnt;
572
573    /*
574     * Break out of the loop if this mbuf is the last in the frame.
575     */
576    if ((bp = bp->next) == NULL)
577      break;
578  }
579
580  /*
581   * Pad short packets.
582   */
583  if  ((packetSize < 64) && (i < MAXIMUM_FRAGS_PER_DESCRIPTOR)) {
584    int padSize = 64 - packetSize;
585    fp->frag_lsw = LSW(padBuf);
586    fp->frag_msw = MSW(padBuf);
587    fp->frag_size = padSize;
588    packetSize += padSize;
589    i++;
590    fp++;
591  }
592
593  /*
594   * Fill Transmit Descriptor
595   */
596  tdp->pkt_size = packetSize;
597  tdp->frag_count = i;
598  tdp->status = 0;
599
600  /*
601   * Chain onto list and start transmission.
602   */
603  tdp->linkp = &fp->frag_link;
604  *tdp->linkp = LSW(tdp->next) | TDA_LINK_EOL;
605  *dp->tdaHead->linkp &= ~TDA_LINK_EOL;
606  sonic_write_register( rp, SONIC_REG_CR, CR_TXP );
607  dp->tdaActiveCount++;
608  dp->tdaHead = tdp;
609
610  /*
611   * Let KA9Q know the packet is on the way.
612   */
613  dp->txWaitTid = 0;
614  *bpp = NULL;
615  return 0;
616}
617
618/*
619 ******************************************************************
620 *                                                                *
621 *                        Receiver Routines                       *
622 *                                                                *
623 ******************************************************************
624 */
625
626/*
627 * Wait for SONIC to hand over a Receive Descriptor.
628 */
629
630SONIC_STATIC void sonic_rda_wait(
631  struct sonic *dp,
632  ReceiveDescriptorPointer_t rdp
633)
634{
635  int i;
636  void *rp = dp->sonic;
637
638  /*
639   * Wait for Receive Descriptor.
640   * The order of the tests is very important.
641   *    The RDA is checked after RBAE is detected.  This ensures that
642   *    the driver processes all RDA entries before reusing the RRA
643   *    entry holding the giant packet.
644   *    The event wait is done after the RDA and RBAE checks.  This
645   *    catches the possibility that a Receive Descriptor became ready
646   *    between the call to this function and the clearing of the
647   *    interrupt status register bit.
648   */
649  for (;;) {
650    /*
651     * Has a giant packet arrived?
652     * The National DP83932C data sheet is very vague on what
653     * happens under this condition.  The description of the
654     * Interrupt Status Register (Section 4.3.6) states,
655     * ``Reception is aborted and the SONIC fetches the next
656     * available resource descriptors in the RRA.  The buffer
657     * space is not re-used and an RDA is not setup for the
658     * truncated packet.''
659     * I take ``Reception is aborted''  to mean that the RXEN
660     * bit in the Command Register is cleared and must be set
661     * by the driver to begin reception again.
662     * Unfortunately, an alternative interpretation could be
663     * that only reception of the current packet is aborted.
664     * This would be more difficult to recover from....
665     */
666    if (sonic_read_register( rp, SONIC_REG_ISR ) & ISR_RBAE) {
667      /*
668       * One more check to soak up any Receive Descriptors
669       * that may already have been handed back to the driver.
670       */
671      if (rdp->in_use == 0)
672        break;
673
674      /*
675       * Check my interpretation of the SONIC manual.
676       */
677      if (sonic_read_register( rp, SONIC_REG_CR ) & CR_RXEN)
678        rtems_panic ("SONIC RBAE/RXEN");
679
680      /*
681       * Update statistics
682       */
683      dp->rxGiant++;
684
685      /*
686       * Reuse receive buffer.
687       * Again, the manual is subject to interpretation.  The
688       * RRP register is described as, `the lower address of
689       * the next descriptor the SONIC will read.''
690       * Since, acording to the ISR/RBAE notes, the SONIC has
691       * ``fetched the next available resource descriptor in
692       * the RRA'', I interpret this to mean that that the
693       * driver has to move the RRP back *two* entries to
694       * reuse the receive buffer holding the giant packet.
695       */
696      for (i = 0 ; i < 2 ; i++) {
697        if (sonic_read_register( rp, SONIC_REG_RRP ) == sonic_read_register( rp, SONIC_REG_RSA ))
698          sonic_write_register(
699            rp,
700            SONIC_REG_RRP,
701            sonic_read_register( rp, SONIC_REG_REA )
702          );
703          sonic_write_register(
704             rp,
705             SONIC_REG_RRP,
706             sonic_read_register(rp, SONIC_REG_RRP) - sizeof(ReceiveResource_t)
707          );
708      }
709
710      /*
711       * Restart reception
712       */
713      sonic_write_register( rp, SONIC_REG_ISR, ISR_RBAE );
714      sonic_write_register( rp, SONIC_REG_CR, CR_RXEN );
715    }
716
717    /*
718     * Clear old packet-received events.
719     */
720    sonic_write_register( rp, SONIC_REG_ISR, ISR_PKTRX );
721
722    /*
723     * Has Receive Descriptor become available?
724     */
725    if (rdp->in_use == 0)
726      break;
727
728    /*
729     * Enable interrupts.
730     */
731    sonic_write_register(
732       rp,
733       SONIC_REG_IMR,
734       sonic_read_register( rp, SONIC_REG_IMR) | (IMR_PRXEN | IMR_RBAEEN)
735    );
736
737    /*
738     * Wait for interrupt.
739     */
740    rtems_ka9q_event_receive (INTERRUPT_EVENT,
741            RTEMS_WAIT|RTEMS_EVENT_ANY,
742            RTEMS_NO_TIMEOUT);
743  }
744}
745
746/*
747 * SCC reader task
748 */
749
750SONIC_STATIC void sonic_rx (int dev, void *p1, void *p2)
751{
752  struct iface *iface = (struct iface *)p1;
753  struct sonic *dp = (struct sonic *)p2;
754  void *rp = dp->sonic;
755  struct mbuf *bp;
756  rtems_unsigned16 status;
757  ReceiveDescriptor_t *rda;
758  ReceiveDescriptorPointer_t ordp, rdp;
759  ReceiveResourcePointer_t rwp, rea;
760  rtems_unsigned16 newMissedTally, oldMissedTally;
761  int i;
762  int continuousCount;
763
764  /*
765   * Set up list in Receive Resource Area.
766   * Allocate space for incoming packets.
767   */
768  rwp = dp->rsa;
769  for (i = 0 ; i < (dp->rdaCount + RRA_EXTRA_COUNT) ; i++, rwp++) {
770    struct mbuf **mbp;
771
772    /*
773     * Allocate memory for buffer.
774     * Place a pointer to the mbuf at the beginning of the buffer
775     * so we can find the mbuf when the SONIC returns the buffer
776     * to the driver.
777     */
778    bp = ambufw (RBUF_SIZE);
779    mbp = (struct mbuf **)bp->data;
780    bp->data += sizeof *mbp;
781    *mbp = bp;
782
783    /*
784     * Set up RRA entry
785     */
786    rwp->buff_ptr_lsw = LSW(bp->data);
787    rwp->buff_ptr_msw = MSW(bp->data);
788    rwp->buff_wc_lsw = RBUF_WC;
789    rwp->buff_wc_msw = 0;
790  }
791  rea = rwp;
792
793  /*
794   * Set up remaining Receive Resource Area pointers
795   */
796  sonic_write_register( rp, SONIC_REG_RSA, LSW(dp->rsa) );
797  sonic_write_register( rp, SONIC_REG_RRP, LSW(dp->rsa) );
798  sonic_write_register( rp, SONIC_REG_REA, LSW(rea) );
799  sonic_write_register( rp, SONIC_REG_RWP, LSW(rea) );
800
801  /*
802   * Set End Of Buffer Count register to the value recommended
803   * in Note 1 of Section 3.4.4.4 of the SONIC data sheet.
804   */
805  sonic_write_register( rp, SONIC_REG_EOBC, RBUF_WC - 2 );
806
807  /*
808   * Set up circular linked list in Receive Descriptor Area.
809   * Leaves ordp pointing at the `end' of the list and
810   * rdp pointing at the `beginning' of the list.
811   */
812  rda = sonic_allocate (dp->rdaCount * sizeof *rda);
813  ordp = rdp = rda;
814  for (i = 0 ; i < dp->rdaCount ; i++) {
815    /*
816     * Set up RDA entry
817     */
818    if (i == (dp->rdaCount - 1))
819      rdp->next = rda;
820    else
821      rdp->next = (ReceiveDescriptor_t *)(rdp + 1);
822    rdp->in_use = 1;
823    ordp = rdp;
824    rdp = rdp->next;
825    ordp->link = LSW(rdp);
826  }
827  ordp->link |= RDA_LINK_EOL;
828  sonic_write_register( rp, SONIC_REG_URDA, MSW(rdp) );
829  sonic_write_register( rp, SONIC_REG_CRDA, LSW(rdp) );
830
831  /*
832   * Start the receiver
833   */
834  oldMissedTally = sonic_read_register( rp, SONIC_REG_MPT );
835  sonic_write_register( rp, SONIC_REG_CR, CR_RRRA );
836  sonic_write_register( rp, SONIC_REG_CR, CR_RXEN );
837
838  /*
839   * Input packet handling loop
840   */
841  continuousCount = 0;
842  for (;;) {
843    /*
844     * Wait till SONIC supplies a Receive Descriptor.
845     */
846    if (rdp->in_use) {
847      continuousCount = 0;
848      sonic_rda_wait (dp, rdp);
849    }
850
851    /*
852     * Check that packet is valid
853     */
854    status = rdp->status;
855    if (status & RDA_STATUS_PRX) {
856      struct mbuf **mbp;
857      void *p;
858
859      /*
860       * Get the mbuf pointer
861       */
862      p = PTR(rdp->pkt_msw, rdp->pkt_lsw);
863      mbp = (struct mbuf **)p - 1;
864      bp = *mbp;
865
866      /*
867       * Pass the packet up the chain.
868       * The mbuf count is reduced to remove
869       * the frame check sequence at the end
870       * of the packet.
871       * ===CACHE===
872       * Invalidate cache entries for this memory.
873       */
874      bp->cnt = rdp->byte_count - sizeof (uint32);
875      net_route (iface, &bp);
876
877      /*
878       * Give the network code a chance to digest the
879       * packet.  This guards against a flurry of
880       * incoming packets (usually an ARP storm) from
881       * using up all the available memory.
882       */
883      if (++continuousCount >= dp->rdaCount)
884        kwait_null ();
885
886      /*
887       * Sanity check that Receive Resource Area is
888       * still in sync with Receive Descriptor Area
889       * The buffer reported in the Receive Descriptor
890       * should be the same as the buffer in the Receive
891       * Resource we are about to reuse.
892       */
893      if ((LSW(p) != rwp->buff_ptr_lsw)
894       || (MSW(p) != rwp->buff_ptr_msw))
895        rtems_panic ("SONIC RDA/RRA");
896
897      /*
898       * Allocate a new mbuf.
899       */
900      bp = ambufw (RBUF_SIZE);
901      mbp = (struct mbuf **)bp->data;
902      bp->data += sizeof *mbp;
903      *mbp = bp;
904
905      /*
906       * Reuse Receive Resource.
907       */
908      rwp->buff_ptr_lsw = LSW(bp->data);
909      rwp->buff_ptr_msw = MSW(bp->data);
910      rwp++;
911      if (rwp == rea)
912        rwp = dp->rsa;
913      sonic_write_register( rp, SONIC_REG_RWP , LSW(rwp) );
914
915      /*
916       * Tell the SONIC to reread the RRA.
917       */
918      if (sonic_read_register( rp, SONIC_REG_ISR ) & ISR_RBE)
919        sonic_write_register( rp, SONIC_REG_ISR, ISR_RBE );
920    }
921    else {
922      if (status & RDA_STATUS_COL)
923        dp->rxCollision++;
924      if (status & RDA_STATUS_FAER)
925        dp->rxNonOctet++;
926      else if (status & RDA_STATUS_CRCR)
927        dp->rxBadCRC++;
928    }
929
930    /*
931     * Count missed packets
932     */
933    newMissedTally = sonic_read_register( rp, SONIC_REG_MPT );
934    if (newMissedTally != oldMissedTally) {
935      dp->rxMissed += (newMissedTally - oldMissedTally) & 0xFFFF;
936      newMissedTally = oldMissedTally;
937    }
938
939    /*
940     * Move to next receive descriptor
941     */
942    rdp->link |= RDA_LINK_EOL;
943    rdp->in_use = 1;
944    ordp->link &= ~RDA_LINK_EOL;
945    ordp = rdp;
946    rdp = rdp->next;
947  }
948}
949
950/*
951 ******************************************************************
952 *                                                                *
953 *                     Initialization Routines                    *
954 *                                                                *
955 ******************************************************************
956 */
957
958/*
959 * Initialize the SONIC hardware
960 */
961SONIC_STATIC void sonic_initialize_hardware(
962  struct sonic *dp,
963  int broadcastFlag
964)
965{
966  void *rp = dp->sonic;
967  int i;
968  unsigned char *hwaddr;
969  rtems_status_code sc;
970  rtems_isr_entry old_handler;
971  TransmitDescriptorPointer_t otdp, tdp;
972  struct CamDescriptor{
973    rtems_unsigned32  cep;  /* CAM Entry Pointer */
974    rtems_unsigned32  cap2; /* CAM Address Port 0 xx-xx-xx-xx-YY-YY */
975    rtems_unsigned32  cap1; /* CAM Address Port 1 xx-xx-YY-YY-xxxx */
976    rtems_unsigned32  cap0; /* CAM Address Port 2 YY-YY-xx-xx-xx-xx */
977    rtems_unsigned32  ce;
978  };
979  volatile struct CamDescriptor *cdp;
980
981  /*
982   * Issue a software reset if necessary.
983   */
984  if ((sonic_read_register( rp, SONIC_REG_CR ) & CR_RST) == 0)
985    sonic_write_register( rp, SONIC_REG_CR, CR_RST );
986
987  /*
988   * Set up data configuration registers.
989   */
990  sonic_write_register( rp, SONIC_REG_DCR, SONIC_DCR );
991/* XXX can not find documentation with this register
992  sonic_write_register( rp, SONIC_REG_DCR2, SONIC_DC2 );
993*/
994
995  /*
996   * Mask all interrupts
997   */
998  sonic_write_register( rp, SONIC_REG_IMR, 0x3fff );
999
1000  /*
1001   * Clear outstanding interrupts.
1002   */
1003  sonic_write_register( rp, SONIC_REG_ISR, 0x7FFF );
1004
1005  /*
1006   * Remove device reset
1007   */
1008  sonic_write_register( rp, SONIC_REG_CR, 0 );
1009 
1010  /*
1011   * Allocate the receive resource area.
1012   * In accordance with National Application Note 746, make the
1013   * receive resource area bigger than the receive descriptor area.
1014   * This has the useful side effect of making the receive resource
1015   * area big enough to hold the CAM descriptor area.
1016   */
1017  dp->rsa = sonic_allocate ((dp->rdaCount + RRA_EXTRA_COUNT) * sizeof *dp->rsa);
1018#ifdef SONIC_DEBUG
1019  printf( "rsa area = %p\n", dp->rsa );
1020#endif
1021  sonic_write_register( rp, SONIC_REG_URRA , MSW(dp->rsa) );
1022
1023  /*
1024   * Set up the SONIC CAM with our hardware address.
1025   * Use the Receive Resource Area to hold the CAM Descriptor Area.
1026   */
1027  hwaddr = dp->iface->hwaddr;
1028  cdp = (struct CamDescriptor *)dp->rsa;
1029  cdp->cep = 0;      /* Fill first entry in CAM */
1030  cdp->cap2 = hwaddr[0] << 8 | hwaddr[1];
1031  cdp->cap1 = hwaddr[2] << 8 | hwaddr[3];
1032  cdp->cap0 = hwaddr[4] << 8 | hwaddr[5];
1033  cdp->ce = 0x0001;    /* Enable first entry in CAM */
1034  sonic_write_register( rp, SONIC_REG_CDC, 1 );      /* One entry in CDA */
1035  sonic_write_register( rp, SONIC_REG_CDP, LSW(cdp) );
1036  sonic_write_register( rp, SONIC_REG_CR, CR_LCAM );  /* Load the CAM */
1037  while (sonic_read_register( rp, SONIC_REG_CR ) & CR_LCAM)
1038    continue;
1039
1040  /*
1041   * Verify that CAM was properly loaded.
1042   */
1043  sonic_write_register( rp, SONIC_REG_CEP, 0 );      /* Select first entry in CAM */
1044  if ((sonic_read_register( rp, SONIC_REG_CAP2 ) != cdp->cap2)
1045   || (sonic_read_register( rp, SONIC_REG_CAP1 ) != cdp->cap1)
1046   || (sonic_read_register( rp, SONIC_REG_CAP0 ) != cdp->cap0)
1047   || (sonic_read_register( rp, SONIC_REG_CE ) != cdp->ce)) {
1048    printf ("Failed to load Ethernet address into SONIC CAM.\n"
1049      "  Wrote %04x%04x%04x - %#x\n"
1050      "   Read %04x%04x%04x - %#x\n",
1051        cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce,
1052        sonic_read_register( rp, SONIC_REG_CAP2 ),
1053        sonic_read_register( rp, SONIC_REG_CAP1 ),
1054        sonic_read_register( rp, SONIC_REG_CAP0 ),
1055        sonic_read_register( rp, SONIC_REG_CE ));
1056    rtems_panic ("SONIC LCAM");
1057  }
1058
1059  /*
1060   * Set up circular linked list in Transmit Descriptor Area.
1061   * Use the PINT bit in the transmit configuration field to
1062   * request an interrupt on every other transmitted packet.
1063   */
1064  dp->tdaActiveCount = 0;
1065  dp->tdaTail = sonic_allocate (dp->tdaCount * sizeof *tdp);
1066  otdp = tdp = dp->tdaTail;
1067  for (i = 0 ; i < dp->tdaCount ; i++) {
1068    if (i & 1)
1069      tdp->pkt_config = TDA_CONFIG_PINT;
1070    else
1071      tdp->pkt_config = 0;
1072    if (i == (dp->tdaCount - 1))
1073      tdp->next = (TransmitDescriptor_t *)dp->tdaTail;
1074    else
1075      tdp->next = (TransmitDescriptor_t *)(tdp + 1);
1076    otdp = tdp;
1077    tdp = tdp->next;
1078  }
1079  dp->tdaHead = otdp;
1080  dp->tdaHead->linkp = &dp->tdaHead->frag[0].frag_link;
1081  sonic_write_register( rp, SONIC_REG_UTDA, MSW(dp->tdaTail) );
1082  sonic_write_register( rp, SONIC_REG_CTDA, LSW(dp->tdaTail) );
1083
1084  /*
1085   * Enable/disable reception of broadcast packets
1086   */
1087  if (broadcastFlag)
1088    sonic_write_register( rp, SONIC_REG_RCR, RCR_BRD );
1089  else
1090    sonic_write_register( rp, SONIC_REG_RCR, 0 );
1091
1092  /*
1093   * Attach SONIC interrupt handler
1094   */
1095  sonic_write_register( rp, SONIC_REG_IMR, 0 );
1096  sc = rtems_interrupt_catch (sonic_interrupt_handler, dp->vector, &old_handler);
1097  if (sc != RTEMS_SUCCESSFUL)
1098    rtems_panic ("Can't attach SONIC interrupt handler: %s\n",
1099              rtems_status_text (sc));
1100
1101  /*
1102   * Remainder of hardware initialization is
1103   * done by the receive and transmit daemons.
1104   */
1105}
1106
1107/*
1108 * Attach an SONIC driver to the system
1109 * This is the only `extern' function in the driver.
1110 *
1111 * argv[0]: interface label, e.g. "rtems"
1112 * The remainder of the arguments are optional key/value pairs:
1113 * mtu ##                  --  maximum transmission unit, default 1500
1114 * broadcast y/n           -- accept or ignore broadcast packets, default yes
1115 * rbuf ##                 -- Set number of receive descriptor entries
1116 * tbuf ##                 -- Set number of transmit descriptor entries
1117 * ip ###.###.###.###      -- IP address
1118 * ether ##:##:##:##:##:## -- Ethernet address
1119 * reg ######              -- Address of SONIC device registers
1120 * vector ###              -- SONIC interrupt vector
1121 */
1122int
1123rtems_ka9q_driver_attach (int argc, char *argv[], void *p)
1124{
1125  struct sonic *dp;
1126  struct iface *iface;
1127  char *cp;
1128  int argIndex;
1129  int broadcastFlag;
1130  char cbuf[30];
1131
1132  /*
1133   * Find an unused entry
1134   */
1135  dp = sonic;
1136  for (;;) {
1137    if (dp == &sonic[NSONIC]) {
1138      printf ("No more SONIC devices.\n");
1139      return -1;
1140    }
1141    if (dp->iface == NULL)
1142      break;
1143    dp++;
1144  }
1145  if (if_lookup (argv[0]) != NULL) {
1146    printf ("Interface %s already exists\n", argv[0]);
1147    return -1;
1148  }
1149
1150  /*
1151   * Create an inteface descriptor
1152   */
1153  iface = callocw (1, sizeof *iface);
1154  iface->name = strdup (argv[0]);
1155  iface->dev = dp - sonic;;
1156
1157  /*
1158   * Set default values
1159   */
1160  broadcastFlag = 1;
1161  dp->txWaitTid = 0;
1162  dp->rdaCount = RDA_COUNT;
1163  dp->tdaCount = TDA_COUNT;
1164  iface->mtu = 1500;
1165  iface->addr = Ip_addr;
1166  iface->hwaddr = mallocw (EADDR_LEN);
1167  memset (iface->hwaddr, 0x08, EADDR_LEN);
1168  dp->sonic = (struct SonicRegisters *)SONIC_BASE_ADDRESS;
1169  dp->vector = SONIC_VECTOR;
1170
1171  /*
1172   * Parse remaining arguments
1173   */
1174  for (argIndex = 1 ; argIndex < (argc - 1) ; argIndex++) {
1175    if (strcmp ("mtu", argv[argIndex]) == 0) {
1176      iface->mtu = strtoul (argv[++argIndex], NULL, 0);
1177    }
1178    else if (strcmp ("broadcast", argv[argIndex]) == 0) {
1179      if (*argv[++argIndex] == 'n')
1180        broadcastFlag = 0;
1181    }
1182    else if (strcmp ("rbuf", argv[argIndex]) == 0) {
1183      /*
1184       * The minimum RDA count is 2.  A single-entry RDA
1185       * would be difficult to use since the SONIC does
1186       * not release (in_use = 0) the RDA that has the
1187       * EOL bit set.
1188       */
1189      dp->rdaCount = strtoul (argv[++argIndex], NULL, 0);
1190      if ((dp->rdaCount <= 1) || (dp->rdaCount > 200)) {
1191        printf ("RDA option (%d) is invalid.\n", dp->rdaCount);
1192        return -1;
1193      }
1194    }
1195    else if (strcmp ("tbuf", argv[argIndex]) == 0) {
1196      dp->tdaCount = strtoul (argv[++argIndex], NULL, 0);
1197      if ((dp->tdaCount <= 1) || (dp->tdaCount > 200)) {
1198        printf ("TDA option (%d) is invalid.\n", dp->tdaCount);
1199        return -1;
1200      }
1201    }
1202    else if (strcmp ("ip", argv[argIndex]) == 0) {
1203      iface->addr = resolve (argv[++argIndex]);
1204    }
1205    else if (strcmp ("ether", argv[argIndex]) == 0) {
1206      gether (iface->hwaddr, argv[++argIndex]);
1207    }
1208    else if (strcmp ("reg", argv[argIndex]) == 0) {
1209      dp->sonic = (struct SonicRegisters *)strtoul (argv[++argIndex], NULL, 0);
1210    }
1211    else if (strcmp ("vector", argv[argIndex]) == 0) {
1212      dp->vector = strtoul (argv[++argIndex], NULL, 0);
1213    }
1214    else {
1215      printf ("Argument %d (%s) is invalid.\n", argIndex, argv[argIndex]);
1216      return -1;
1217    }
1218  }
1219  printf ("Ethernet address: %s\n", pether (cbuf, iface->hwaddr));
1220  iface->raw = sonic_raw;
1221  iface->stop = sonic_stop;
1222  iface->show = sonic_show;
1223  dp->iface = iface;
1224  setencap (iface, "Ethernet");
1225
1226  /*
1227   * Set up SONIC hardware
1228   */
1229  sonic_initialize_hardware (dp, broadcastFlag);
1230
1231  /*
1232   * Chain onto list of interfaces
1233   */
1234  iface->next = Ifaces;
1235  Ifaces = iface;
1236
1237  /*
1238   * Start I/O daemons
1239   */
1240  cp = if_name (iface, " tx");
1241  iface->txproc = newproc (cp, 2048, if_tx, iface->dev, iface, NULL, 0);
1242  free (cp);
1243  cp = if_name (iface, " rx");
1244  iface->rxproc = newproc (cp, 2048, sonic_rx, iface->dev, iface, dp, 0);
1245  free (cp);
1246  return 0;
1247}
1248
1249#ifdef SONIC_DEBUG
1250#include <stdio.h>
1251#endif
1252
1253void sonic_write_register(
1254  void       *base,
1255  unsigned32  regno,
1256  unsigned32  value
1257)
1258{
1259  volatile unsigned32 *p = base;
1260
1261#ifdef SONIC_DEBUG
1262  printf( "Write 0x%04x to 0x%02x\n", value, regno );
1263  fflush( stdout );
1264#endif
1265  p[regno] = value;
1266}
1267
1268unsigned32 sonic_read_register(
1269  void       *base,
1270  unsigned32  regno
1271)
1272{
1273  volatile unsigned32 *p = base;
1274  unsigned32           value;
1275
1276  value = p[regno];
1277#ifdef SONIC_DEBUG
1278  printf( "Read 0x%04x from 0x%02x\n", value, regno );
1279  fflush( stdout );
1280#endif
1281  return value;
1282}
1283
Note: See TracBrowser for help on using the repository browser.