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

4.104.114.84.9
Last change on this file since fa655207 was fa655207, checked in by Joel Sherrill <joel.sherrill@…>, on Jul 30, 1998 at 10:57:12 PM

Added temporary include of dmv170.h

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