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

4.104.114.84.9
Last change on this file since 4fbf114 was c932d85, checked in by Joel Sherrill <joel.sherrill@…>, on May 30, 1998 at 10:09:14 AM

New files -- from rtems-LM-980406 which was based on an RTEMS from 12/97.
This was called the dmv170 BSP in that source tree but since the DMV171
is now obsolete, we have transitioned to the DMV177 and have no intention
of checking compatibility with any other models.

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