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

4.104.114.84.95
Last change on this file since 4f38b713 was 4f38b713, checked in by Joel Sherrill <joel.sherrill@…>, on 08/12/98 at 16:28:17

Fixed bug where the last link of the RDA was not initialized properly.

  • Property mode set to 100644
File size: 41.4 KB
Line 
1void break_when_you_get_here();
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 * Debug levels
46 *
47 */
48
49#define SONIC_DEBUG_NONE             0x0000
50#define SONIC_DEBUG_ALL              0xFFFF
51#define SONIC_DEBUG_PRINT_REGISTERS  0x0001
52#define SONIC_DEBUG_MEMORY           0x0002
53#define SONIC_DEBUG_MEMORY_ALLOCATE  0x0004
54#define SONIC_DEBUG_FRAGMENTS        0x0008
55#define SONIC_DEBUG_CAM              0x0008
56#define SONIC_DEBUG_DESCRIPTORS      0x0010
57
58#define SONIC_DEBUG (SONIC_DEBUG_NONE)
59
60/* (SONIC_DEBUG_MEMORY|SONIC_DEBUG_DESCRIPTORS) */
61
62/* SONIC_DEBUG_ALL */
63
64
65/*
66 * XXX
67 */
68
69#include <dmv170.h>
70
71/*
72 *  Use the top line if you want more symbols.
73 */
74
75#define SONIC_STATIC
76/* #define SONIC_STATIC static */
77
78/*
79 * Number of devices supported by this driver
80 */
81#ifndef NSONIC
82# define NSONIC 1
83#endif
84
85/*
86 * Default location of device registers
87 */
88#ifndef SONIC_BASE_ADDRESS
89# define SONIC_BASE_ADDRESS 0xF3000000
90# warning "Using default SONIC_BASE_ADDRESS."
91#endif
92
93/*
94 * Default interrupt vector
95 */
96#ifndef SONIC_VECTOR
97# define SONIC_VECTOR 1
98# warning "Using default SONIC_VECTOR."
99#endif
100
101/*
102 * Default device configuration register values
103 * Conservative, generic values.
104 * DCR:
105 *      No extended bus mode
106 *      Unlatched bus retry
107 *      Programmable outputs unused
108 *      Asynchronous bus mode
109 *      User definable pins unused
110 *      No wait states (access time controlled by DTACK*)
111 *      32-bit DMA
112 *      Empty/Fill DMA mode
113 *      Maximum Transmit/Receive FIFO
114 * DC2:
115 *      Extended programmable outputs unused
116 *      Normal HOLD request
117 *      Packet compress output unused
118 *      No reject on CAM match
119 */
120#define SONIC_DCR \
121   (DCR_DW32 | DCR_WAIT0 | DCR_PO0 | DCR_PO1  | DCR_RFT24 | DCR_TFT28)
122#ifndef SONIC_DCR
123# define SONIC_DCR (DCR_DW32 | DCR_TFT28)
124#endif
125#ifndef SONIC_DC2
126# define SONIC_DC2 (0)
127#endif
128
129/*
130 * Default sizes of transmit and receive descriptor areas
131 */
132#define RDA_COUNT     20
133#define TDA_COUNT     10
134
135/*
136 *
137 * As suggested by National Application Note 746, make the
138 * receive resource area bigger than the receive descriptor area.
139 */
140#define RRA_EXTRA_COUNT  3
141
142/*
143 * RTEMS event used by interrupt handler to signal daemons.
144 */
145#define INTERRUPT_EVENT  RTEMS_EVENT_1
146
147/*
148 * Largest Ethernet frame.
149 */
150#define MAXIMUM_FRAME_SIZE  1518
151
152/*
153 * Receive buffer size.
154 * Allow for a pointer, plus a full ethernet frame (including Frame
155 * Check Sequence) rounded up to a 4-byte boundary.
156 */
157#define RBUF_SIZE  ((sizeof (void *) + (MAXIMUM_FRAME_SIZE) + 3) & ~3)
158#define RBUF_WC    ((((MAXIMUM_FRAME_SIZE) + 3) & ~3) / 2)
159
160/*
161 * Macros for manipulating 32-bit pointers as 16-bit fragments
162 */
163#define LSW(p)   ((rtems_unsigned16)((rtems_unsigned32)(p)))
164#define MSW(p)   ((rtems_unsigned16)((rtems_unsigned32)(p) >> 16))
165#define PTR(m,l) ((void*)(((rtems_unsigned16)(m)<<16)|(rtems_unsigned16)(l)))
166
167/*
168 * Hardware-specific storage
169 */
170struct sonic {
171  /*
172   * Connection to KA9Q
173   */
174  struct iface                     *iface;
175
176  /*
177   * Default location of device registers
178   * ===CACHE===
179   * This area must be non-cacheable, guarded.
180   */
181  void                             *sonic;
182
183  /*
184   * Interrupt vector
185   */
186  rtems_vector_number             vector;
187
188  /*
189   * Task waiting for transmit resources
190   */
191  rtems_id                        txWaitTid;
192
193  /*
194   * Receive resource area
195   */
196  int                             rdaCount;
197  ReceiveResourcePointer_t        rsa;
198  ReceiveResourcePointer_t        rea;
199  CamDescriptorPointer_t          cdp;
200  ReceiveDescriptorPointer_t      rda;
201  ReceiveDescriptorPointer_t      rdp_last;
202
203  /*
204   * Transmit descriptors
205   */
206  int                             tdaCount;
207  TransmitDescriptorPointer_t     tdaHead;  /* Last filled */
208  TransmitDescriptorPointer_t     tdaTail;  /* Next to retire */
209  int                             tdaActiveCount;
210
211  /*
212   * Statistics
213   */
214  unsigned long                   Interrupts;
215  unsigned long                   rxInterrupts;
216  unsigned long                   rxMissed;
217  unsigned long                   rxGiant;
218  unsigned long                   rxNonOctet;
219  unsigned long                   rxBadCRC;
220  unsigned long                   rxCollision;
221
222  unsigned long                   txInterrupts;
223  unsigned long                   txSingleCollision;
224  unsigned long                   txMultipleCollision;
225  unsigned long                   txCollision;
226  unsigned long                   txDeferred;
227  unsigned long                   txUnderrun;
228  unsigned long                   txLateCollision;
229  unsigned long                   txExcessiveCollision;
230  unsigned long                   txExcessiveDeferral;
231  unsigned long                   txLostCarrier;
232  unsigned long                   txRawWait;
233};
234SONIC_STATIC struct sonic sonic[NSONIC];
235
236/*
237 ******************************************************************
238 *                                                                *
239 *                        Support Routines                        *
240 *                                                                *
241 ******************************************************************
242 */
243
244void sonic_write_register(
245  void       *base,
246  unsigned32  regno,
247  unsigned32  value
248);
249
250unsigned32 sonic_read_register(
251  void       *base,
252  unsigned32  regno
253);
254
255/*
256 * Allocate non-cacheable memory on a single 64k page.
257 * Very simple minded -- just keeps trying till the memory is on a single page.
258 */
259SONIC_STATIC void * sonic_allocate(unsigned int nbytes)
260{
261  void *p;
262  unsigned long a1, a2;
263
264  for (;;) {
265    /*
266     * ===CACHE===
267     * Change malloc to malloc_noncacheable_guarded.
268     */
269    p = calloc(1, nbytes);
270    if (p == NULL)
271      rtems_panic ("No memory!");
272    a1 = (unsigned long)p;
273    a2 = a1 + nbytes - 1;
274    if ((a1 >> 16) == (a2 >> 16))
275      break;
276  }
277#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_ALLOCATE)
278  printf( "sonic_allocate %d bytes at %p\n", nbytes, p );
279#endif
280  return p;
281}
282
283/*
284 * Shut down the interface.
285 * This is a pretty simple-minded routine.  It doesn't worry
286 * about cleaning up mbufs, shutting down daemons, etc.
287 */
288
289SONIC_STATIC int sonic_stop (struct iface *iface)
290{
291  int i;
292  struct sonic *dp = &sonic[iface->dev];
293  void *rp = dp->sonic;
294
295  /*
296   * Stop the transmitter and receiver.
297   */
298  sonic_write_register( rp, SONIC_REG_CR, CR_HTX | CR_RXDIS );
299
300  /*
301   * Wait for things to stop.
302   * For safety's sake, there is an alternate exit.
303   */
304  i = 0;
305  while (sonic_read_register( rp, SONIC_REG_CR ) & (CR_RXEN | CR_TXP)) {
306    if (++i == 10000)
307      break;
308  }
309
310  /*
311   * Reset the device
312   */
313  sonic_write_register( rp, SONIC_REG_CR, CR_RST );
314  sonic_write_register( rp, SONIC_REG_IMR, 0 );
315  return 0;
316}
317
318/*
319 * Show interface statistics
320 */
321
322SONIC_STATIC void sonic_show (struct iface *iface)
323{
324  struct sonic *dp = &sonic[iface->dev];
325
326  printf (" Total Interrupts:%-8lu", dp->Interrupts);
327  printf ("    Rx Interrupts:%-8lu", dp->rxInterrupts);
328  printf ("            Giant:%-8lu", dp->rxGiant);
329  printf ("        Non-octet:%-8lu\n", dp->rxNonOctet);
330  printf ("          Bad CRC:%-8lu", dp->rxBadCRC);
331  printf ("        Collision:%-8lu", dp->rxCollision);
332  printf ("           Missed:%-8lu\n", dp->rxMissed);
333
334  printf (    "    Tx Interrupts:%-8lu", dp->txInterrupts);
335  printf (  "           Deferred:%-8lu", dp->txDeferred);
336  printf ("        Lost Carrier:%-8lu\n", dp->txLostCarrier);
337  printf (   "Single Collisions:%-8lu", dp->txSingleCollision);
338  printf ( "Multiple Collisions:%-8lu", dp->txMultipleCollision);
339  printf ("Excessive Collisions:%-8lu\n", dp->txExcessiveCollision);
340  printf (   " Total Collisions:%-8lu", dp->txCollision);
341  printf ( "     Late Collision:%-8lu", dp->txLateCollision);
342  printf ("            Underrun:%-8lu\n", dp->txUnderrun);
343  printf (   "  Raw output wait:%-8lu\n", dp->txRawWait);
344}
345
346/*
347 ******************************************************************
348 *                                                                *
349 *                        Interrupt Handler                       *
350 *                                                                *
351 ******************************************************************
352 */
353
354SONIC_STATIC rtems_isr sonic_interrupt_handler (rtems_vector_number v)
355{
356  struct sonic *dp = sonic;
357  void *rp;
358
359#if (NSONIC > 1)
360  /*
361   * Find the device which requires service
362   */
363  for (;;) {
364    if (dp->vector == v)
365      break;
366    if (++dp == &sonic[NSONIC])
367      return;  /* Spurious interrupt? */
368  }
369#endif /* NSONIC > 1 */
370
371  /*
372   * Get pointer to SONIC registers
373   */
374  rp = dp->sonic;
375
376  dp->Interrupts++;
377
378  /*
379   * Packet received or receive buffer area exceeded?
380   */
381  if ((sonic_read_register( rp, SONIC_REG_IMR ) & (IMR_PRXEN | IMR_RBAEEN)) &&
382      (sonic_read_register( rp, SONIC_REG_ISR ) & (ISR_PKTRX | ISR_RBAE))) {
383    sonic_write_register(
384       rp,
385       SONIC_REG_IMR,
386       sonic_read_register( rp, SONIC_REG_IMR) & ~(IMR_PRXEN | IMR_RBAEEN)
387    );
388    dp->rxInterrupts++;
389    rtems_event_send (dp->iface->rxproc, INTERRUPT_EVENT);
390  }
391
392  /*
393   * Packet started, transmitter done or transmitter error?
394   */
395  if ((sonic_read_register( rp, SONIC_REG_IMR ) & (IMR_PINTEN | IMR_PTXEN | IMR_TXEREN))
396   && (sonic_read_register( rp, SONIC_REG_ISR ) & (ISR_PINT | ISR_TXDN | ISR_TXER))) {
397    sonic_write_register(
398       rp,
399       SONIC_REG_IMR,
400       sonic_read_register( rp, SONIC_REG_IMR) &
401                  ~(IMR_PINTEN | IMR_PTXEN | IMR_TXEREN)
402    );
403    dp->txInterrupts++;
404    rtems_event_send (dp->txWaitTid, INTERRUPT_EVENT);
405  }
406}
407
408/*
409 ******************************************************************
410 *                                                                *
411 *                      Transmitter Routines                      *
412 *                                                                *
413 ******************************************************************
414 */
415
416/*
417 * Soak up transmit descriptors that have been sent.
418 */
419
420SONIC_STATIC void sonic_retire_tda (struct sonic *dp)
421{
422  rtems_unsigned16 status;
423  unsigned int collisions;
424
425  /*
426   * Repeat for all completed transmit descriptors.
427   */
428  while ((dp->tdaActiveCount != 0)
429      && ((status = dp->tdaTail->status) != 0)) {
430
431#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)
432    printf( "retire TDA %p (0x%04x)\n", dp->tdaTail, status );
433#endif
434
435    /*
436     * Check for errors which stop the transmitter.
437     */
438    if (status & (TDA_STATUS_EXD |
439        TDA_STATUS_EXC |
440        TDA_STATUS_FU |
441        TDA_STATUS_BCM)) {
442      /*
443       * Restart the transmitter if there are
444       * packets waiting to go.
445       */
446      rtems_unsigned16 link;
447      link = *(dp->tdaTail->linkp);
448
449      if ((link & TDA_LINK_EOL) == 0) {
450        void *rp = dp->sonic;
451
452        sonic_write_register( rp, SONIC_REG_CTDA, link );
453        sonic_write_register( rp, SONIC_REG_CR, CR_TXP );
454      }
455    }
456
457    /*
458     * Update network statistics
459     */
460    collisions = (status & TDA_STATUS_COLLISION_MASK) >> TDA_STATUS_COLLISION_SHIFT;
461    if (collisions) {
462      if (collisions == 1)
463        dp->txSingleCollision++;
464      else
465        dp->txMultipleCollision++;
466      dp->txCollision += collisions;
467    }
468    if (status & TDA_STATUS_EXC)
469      dp->txExcessiveCollision++;
470    if (status & TDA_STATUS_OWC)
471      dp->txLateCollision++;
472    if (status & TDA_STATUS_EXD)
473      dp->txExcessiveDeferral++;
474    if (status & TDA_STATUS_DEF)
475      dp->txDeferred++;
476    if (status & TDA_STATUS_FU)
477      dp->txUnderrun++;
478    if (status & TDA_STATUS_CRSL)
479      dp->txLostCarrier++;
480
481    /*
482     * Free the packet
483     */
484    dp->tdaActiveCount--;
485    free_p ((struct mbuf **)&dp->tdaTail->mbufp);
486
487/*  XXX this does not help when you wrap */
488    dp->tdaTail->frag[0].frag_link = LSW(dp->tdaTail->link_pad);
489    dp->tdaTail->frag_count        = 0;
490
491    /*
492     * Move to the next transmit descriptor
493     */
494    dp->tdaTail = dp->tdaTail->next;
495#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)
496    printf( "next TDA %p\n", dp->tdaTail );
497#endif
498  }
499}
500
501/*
502 * Send raw packet (caller provides header).
503 * This code runs in the context of the interface transmit
504 * task (most packets)  or in the context of the network
505 * task (for ARP requests).
506 */
507
508SONIC_STATIC int sonic_raw (struct iface *iface, struct mbuf **bpp)
509{
510  struct sonic *dp = &sonic[iface->dev];
511  void *rp = dp->sonic;
512  struct mbuf *bp;
513  TransmitDescriptorPointer_t tdp;
514  volatile struct TransmitDescriptorFragLink *fp;
515  unsigned int packetSize;
516  int i;
517  static char padBuf[64];
518
519  /*
520   * Update the log.
521   */
522  iface->rawsndcnt++;
523  iface->lastsent = secclock ();
524  dump (iface, IF_TRACE_OUT, *bpp);
525
526  /*
527   * It would not do to have two tasks active in the transmit
528   * loop at the same time.
529   * The blocking is simple-minded since the odds of two tasks
530   * simultaneously attempting to use this code are low.  The only
531   * way that two tasks can try to run here is:
532   *  1) Task A enters this code and ends up having to
533   *     wait for a transmit buffer descriptor.
534   *  2) Task B gains control and tries to transmit a packet.
535   * The RTEMS/KA9Q scheduling semaphore ensures that there
536   * are no race conditions associated with manipulating the
537   * txWaitTid variable.
538   */
539  if (dp->txWaitTid) {
540    dp->txRawWait++;
541    while (dp->txWaitTid)
542      rtems_ka9q_ppause (10);
543  }
544
545  /*
546   * Free up transmit descriptors.
547   */
548  sonic_retire_tda (dp);
549
550  /*
551   * Wait for transmit descriptor to become available.
552   */
553  if (dp->tdaActiveCount == dp->tdaCount) {
554puts( "Wait for more TDAs" );
555    /*
556     * Find out who we are
557     */
558    if (dp->txWaitTid == 0)
559      rtems_task_ident (RTEMS_SELF, 0, &dp->txWaitTid);
560
561    /*
562     * Clear old events.
563     */
564    sonic_write_register( rp, SONIC_REG_ISR, ISR_PINT | ISR_TXDN | ISR_TXER );
565
566    /*
567     * Wait for transmit descriptor to become available.
568     * Note that the transmit descriptors are checked
569     * *before* * entering the wait loop -- this catches
570     * the possibility that a transmit descriptor became
571     * available between the `if' the started this block,
572     * and the clearing of the interrupt status register.
573     */
574    sonic_retire_tda (dp);
575    while (dp->tdaActiveCount == dp->tdaCount) {
576      /*
577       * Enable transmitter interrupts.
578       */
579      sonic_write_register(
580         rp,
581         SONIC_REG_IMR,
582         sonic_read_register( rp, SONIC_REG_IMR) |
583                (IMR_PINTEN | IMR_PTXEN | IMR_TXEREN)
584      );
585
586      /*
587       * Wait for interrupt
588       */
589      rtems_ka9q_event_receive (INTERRUPT_EVENT,
590            RTEMS_WAIT|RTEMS_EVENT_ANY,
591            RTEMS_NO_TIMEOUT);
592      sonic_write_register( rp, SONIC_REG_ISR, ISR_PINT | ISR_TXDN | ISR_TXER );
593      sonic_retire_tda (dp);
594    }
595  }
596
597  /*
598   * Get the head of the packet mbuf chain.
599   */
600  bp = *bpp;
601
602  /*
603   * Fill in the transmit descriptor fragment descriptors.
604   * ===CACHE===
605   * If data cache is operating in write-back mode, flush cached
606   * data to memory.
607   */
608  tdp = dp->tdaHead->next;
609  tdp->mbufp = bp;
610  packetSize = 0;
611  fp = tdp->frag;
612  for (i = 0 ; i < MAXIMUM_FRAGS_PER_DESCRIPTOR ; i++, fp++) {
613    fp->frag_lsw = LSW(bp->data);
614    fp->frag_msw = MSW(bp->data);
615    fp->frag_size = bp->cnt;
616    packetSize += bp->cnt;
617
618#if (SONIC_DEBUG & SONIC_DEBUG_FRAGMENTS)
619    printf( "fp %p 0x%04x%04x %d\n",
620      fp, fp->frag_msw, fp->frag_lsw, fp->frag_size );
621#endif
622    /*
623     * Break out of the loop if this mbuf is the last in the frame.
624     */
625    if ((bp = bp->next) == NULL)
626      break;
627  }
628
629  /*
630   * Pad short packets.
631   */
632  if  ((packetSize < 64) && (i < MAXIMUM_FRAGS_PER_DESCRIPTOR)) {
633    int padSize = 64 - packetSize;
634    fp++;
635    fp->frag_lsw = LSW(padBuf);
636    fp->frag_msw = MSW(padBuf);
637    fp->frag_size = padSize;
638#if (SONIC_DEBUG & SONIC_DEBUG_FRAGMENTS)
639    printf( "PAD fp %p 0x%04x%04x %d\n",
640         fp, fp->frag_msw, fp->frag_lsw, fp->frag_size );
641#endif
642    packetSize += padSize;
643    i++;
644  }
645
646  /*
647   * Fill Transmit Descriptor
648   */
649  tdp->pkt_size = packetSize;
650  tdp->frag_count = i + 1;
651  tdp->status = 0;
652
653  /*
654   * Chain onto list and start transmission.
655   */
656
657  tdp->linkp = &(fp+1)->frag_link;
658  *tdp->linkp = LSW(tdp->next) | TDA_LINK_EOL;
659  if ( dp->tdaHead->frag_count )
660    *dp->tdaHead->linkp &= ~TDA_LINK_EOL;
661  dp->tdaActiveCount++;
662  dp->tdaHead = tdp;
663
664  sonic_write_register(
665     rp,
666     SONIC_REG_IMR,
667     sonic_read_register( rp, SONIC_REG_IMR) |
668            (IMR_PINTEN | IMR_PTXEN | IMR_TXEREN)
669  );
670  sonic_write_register( rp, SONIC_REG_CR, CR_TXP );
671
672  /*
673   * Let KA9Q know the packet is on the way
674   */
675
676  dp->txWaitTid = 0;
677  *bpp = NULL;
678  return 0;
679}
680
681/*
682 ******************************************************************
683 *                                                                *
684 *                        Receiver Routines                       *
685 *                                                                *
686 ******************************************************************
687 */
688
689/*
690 * Wait for SONIC to hand over a Receive Descriptor.
691 */
692
693SONIC_STATIC void sonic_rda_wait(
694  struct sonic *dp,
695  ReceiveDescriptorPointer_t rdp
696)
697{
698  int i;
699  void *rp = dp->sonic;
700
701  /*
702   * Wait for Receive Descriptor.
703   * The order of the tests is very important.
704   *    The RDA is checked after RBAE is detected.  This ensures that
705   *    the driver processes all RDA entries before reusing the RRA
706   *    entry holding the giant packet.
707   *    The event wait is done after the RDA and RBAE checks.  This
708   *    catches the possibility that a Receive Descriptor became ready
709   *    between the call to this function and the clearing of the
710   *    interrupt status register bit.
711   */
712  for (;;) {
713    /*
714     * Has a giant packet arrived?
715     * The National DP83932C data sheet is very vague on what
716     * happens under this condition.  The description of the
717     * Interrupt Status Register (Section 4.3.6) states,
718     * ``Reception is aborted and the SONIC fetches the next
719     * available resource descriptors in the RRA.  The buffer
720     * space is not re-used and an RDA is not setup for the
721     * truncated packet.''
722     * I take ``Reception is aborted''  to mean that the RXEN
723     * bit in the Command Register is cleared and must be set
724     * by the driver to begin reception again.
725     * Unfortunately, an alternative interpretation could be
726     * that only reception of the current packet is aborted.
727     * This would be more difficult to recover from....
728     */
729    if (sonic_read_register( rp, SONIC_REG_ISR ) & ISR_RBAE) {
730      /*
731       * One more check to soak up any Receive Descriptors
732       * that may already have been handed back to the driver.
733       */
734      if (rdp->in_use == RDA_IN_USE)
735        break;
736
737      /*
738       * Check my interpretation of the SONIC manual.
739       */
740      if (sonic_read_register( rp, SONIC_REG_CR ) & CR_RXEN)
741        rtems_panic ("SONIC RBAE/RXEN");
742
743      /*
744       * Update statistics
745       */
746      dp->rxGiant++;
747
748      /*
749       * Reuse receive buffer.
750       * Again, the manual is subject to interpretation.  The
751       * RRP register is described as, `the lower address of
752       * the next descriptor the SONIC will read.''
753       * Since, acording to the ISR/RBAE notes, the SONIC has
754       * ``fetched the next available resource descriptor in
755       * the RRA'', I interpret this to mean that that the
756       * driver has to move the RRP back *two* entries to
757       * reuse the receive buffer holding the giant packet.
758       */
759      for (i = 0 ; i < 2 ; i++) {
760        if (sonic_read_register( rp, SONIC_REG_RRP ) ==
761            sonic_read_register( rp, SONIC_REG_RSA ))
762          sonic_write_register(
763            rp,
764            SONIC_REG_RRP,
765            sonic_read_register( rp, SONIC_REG_REA )
766          );
767          sonic_write_register(
768             rp,
769             SONIC_REG_RRP,
770             sonic_read_register(rp, SONIC_REG_RRP) - sizeof(ReceiveResource_t)
771          );
772      }
773
774      /*
775       * Restart reception
776       */
777      sonic_write_register( rp, SONIC_REG_ISR, ISR_RBAE );
778      sonic_write_register( rp, SONIC_REG_CR, CR_RXEN );
779    }
780
781    /*
782     * Clear old packet-received events.
783     */
784    sonic_write_register( rp, SONIC_REG_ISR, ISR_PKTRX );
785
786    /*
787     * Has Receive Descriptor become available?
788     */
789    if (rdp->in_use == RDA_IN_USE)
790      break;
791
792    /*
793     * Enable interrupts.
794     */
795    sonic_write_register(
796       rp,
797       SONIC_REG_IMR,
798       sonic_read_register( rp, SONIC_REG_IMR) | (IMR_PRXEN | IMR_RBAEEN)
799    );
800
801    /*
802     * Wait for interrupt.
803     */
804    rtems_ka9q_event_receive (INTERRUPT_EVENT,
805            RTEMS_WAIT|RTEMS_EVENT_ANY,
806            RTEMS_NO_TIMEOUT);
807  }
808#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)
809  printf( "RDA %p\n", rdp );
810#endif
811}
812
813/*
814 * SCC reader task
815 */
816
817SONIC_STATIC void sonic_rx (int dev, void *p1, void *p2)
818{
819  struct iface *iface = (struct iface *)p1;
820  struct sonic *dp = (struct sonic *)p2;
821  void *rp = dp->sonic;
822  struct mbuf *bp;
823  rtems_unsigned16 status;
824  ReceiveDescriptorPointer_t rdp;
825  ReceiveResourcePointer_t rwp, rea;
826  rtems_unsigned16 newMissedTally, oldMissedTally;
827  int continuousCount;
828
829  rwp = dp->rsa;
830  rea = dp->rea; /* XXX was rwp; */
831  rdp = dp->rda; /* XXX was rdp_last */
832
833  /*
834   * Start the receiver
835   */
836  oldMissedTally = sonic_read_register( rp, SONIC_REG_MPT );
837  sonic_write_register( rp, SONIC_REG_CR, CR_RRRA );
838  sonic_write_register( rp, SONIC_REG_CR, CR_RXEN );
839
840  /*
841   * Input packet handling loop
842   */
843  continuousCount = 0;
844  for (;;) {
845    /*
846     * Wait till SONIC supplies a Receive Descriptor.
847     */
848    if (rdp->in_use == RDA_FREE) {
849      continuousCount = 0;
850      sonic_rda_wait (dp, rdp);
851    }
852
853#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)
854    printf( "Incoming packet %p status=0x%04x\n", rdp, rdp->status );
855#endif
856
857    /*
858     * Check that packet is valid
859     */
860    status = rdp->status;
861    if (status & RDA_STATUS_PRX) {
862      struct mbuf **mbp;
863      void *p;
864
865/* printf( "Valid packet\n" ); */
866      /*
867       * Get the mbuf pointer
868       */
869      p = PTR(rdp->pkt_msw, rdp->pkt_lsw);
870      mbp = (struct mbuf **)p - 1;
871      bp = *mbp;
872
873      /*
874       * Pass the packet up the chain.
875       * The mbuf count is reduced to remove
876       * the frame check sequence at the end
877       * of the packet.
878       * ===CACHE===
879       * Invalidate cache entries for this memory.
880       */
881      bp->cnt = rdp->byte_count - sizeof (uint32);
882/* printf( "Routing the packet\n" ); */
883      net_route (iface, &bp);
884
885      /*
886       * Give the network code a chance to digest the
887       * packet.  This guards against a flurry of
888       * incoming packets (usually an ARP storm) from
889       * using up all the available memory.
890       */
891      if (++continuousCount >= dp->rdaCount)
892        kwait_null ();
893
894      /*
895       * Sanity check that Receive Resource Area is
896       * still in sync with Receive Descriptor Area
897       * The buffer reported in the Receive Descriptor
898       * should be the same as the buffer in the Receive
899       * Resource we are about to reuse.
900       */
901/* XXX figure out whether this is valid or not */
902#if 0
903      if ((LSW(p) != rwp->buff_ptr_lsw)
904       || (MSW(p) != rwp->buff_ptr_msw))
905        rtems_panic ("SONIC RDA/RRA");
906#endif
907
908      /*
909       * Allocate a new mbuf.
910       */
911      bp = ambufw (RBUF_SIZE);
912      mbp = (struct mbuf **)bp->data;
913      bp->data += sizeof *mbp;
914      *mbp = bp;
915
916      /*
917       * Reuse Receive Resource.
918       */
919      rwp->buff_ptr_lsw = LSW(bp->data);
920      rwp->buff_ptr_msw = MSW(bp->data);
921      rwp++;
922      if (rwp == rea) {
923#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
924        printf( "Wrapping RWP from %p to %p\n", rwp, dp->rsa );
925#endif
926        rwp = dp->rsa;
927      }
928      sonic_write_register( rp, SONIC_REG_RWP , LSW(rwp) );
929
930      /*
931       * Tell the SONIC to reread the RRA.
932       */
933      if (sonic_read_register( rp, SONIC_REG_ISR ) & ISR_RBE)
934        sonic_write_register( rp, SONIC_REG_ISR, ISR_RBE );
935    }
936    else {
937      if (status & RDA_STATUS_COL)
938        dp->rxCollision++;
939      if (status & RDA_STATUS_FAER)
940        dp->rxNonOctet++;
941      else if (status & RDA_STATUS_CRCR)
942        dp->rxBadCRC++;
943    }
944
945    /*
946     * Count missed packets
947     */
948    newMissedTally = sonic_read_register( rp, SONIC_REG_MPT );
949    if (newMissedTally != oldMissedTally) {
950      dp->rxMissed += (newMissedTally - oldMissedTally) & 0xFFFF;
951      newMissedTally = oldMissedTally;
952    }
953
954    /*
955     * Move to next receive descriptor
956     */
957    rdp->link |= RDA_LINK_EOL;
958    rdp->in_use = RDA_FREE;
959    rdp = rdp->next;
960    rdp->link &= ~RDA_LINK_EOL;
961  }
962}
963
964/*
965 ******************************************************************
966 *                                                                *
967 *                     Initialization Routines                    *
968 *                                                                *
969 ******************************************************************
970 */
971
972/*
973 * Initialize the SONIC hardware
974 */
975SONIC_STATIC void sonic_initialize_hardware(
976  struct sonic *dp,
977  int broadcastFlag
978)
979{
980  void *rp = dp->sonic;
981  int i;
982  unsigned char *hwaddr;
983  rtems_isr_entry old_handler;
984  TransmitDescriptorPointer_t tdp;
985  ReceiveDescriptorPointer_t ordp, rdp;
986  ReceiveResourcePointer_t rwp;
987  struct mbuf *bp;
988  CamDescriptorPointer_t cdp;
989
990  /*
991   *  The Revision B SONIC has a horrible bug known as the "Zero
992   *  Length Packet bug".  The initial board used to develop this
993   *  driver had a newer revision of the SONIC so there was no reason
994   *  to check for this.  If you have the Revision B SONIC chip, then
995   *  you need to add some code to the RX path to handle this weirdness.
996   */
997
998  if ( sonic_read_register( rp, SONIC_REG_SR ) < SONIC_REVISION_C ) {
999    rtems_fatal_error_occurred( 0x0BADF00D );  /* don't eat this part :) */
1000  }
1001 
1002  /*
1003   *  Set up circular linked list in Transmit Descriptor Area.
1004   *  Use the PINT bit in the transmit configuration field to
1005   *  request an interrupt on every other transmitted packet.
1006   *
1007   *  NOTE: sonic_allocate() zeroes all of the memory allocated.
1008   */
1009
1010  dp->tdaActiveCount = 0;
1011  dp->tdaTail = sonic_allocate(dp->tdaCount * sizeof *tdp);
1012#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
1013  printf( "tdaTail = %p\n", dp->tdaTail );
1014#endif
1015  tdp = dp->tdaTail;
1016  for (i = 0 ; i < dp->tdaCount ; i++) {
1017    /*
1018     *  status, pkt_config, pkt_size, and all fragment fields
1019     *  are set to zero by sonic_allocate.
1020     */
1021
1022/* XXX not used by other drivers we looked at
1023    if (i & 1)
1024      tdp->pkt_config = TDA_CONFIG_PINT;
1025*/
1026
1027    tdp->frag_count        = 0;
1028    tdp->frag[0].frag_link = LSW(tdp + 1);
1029    tdp->link_pad          = LSW(tdp + 1) | TDA_LINK_EOL;
1030    tdp->linkp             = &((tdp + 1)->frag[0].frag_link);
1031    tdp->next              = (TransmitDescriptor_t *)(tdp + 1);
1032    tdp++;
1033  }
1034  tdp--;
1035  dp->tdaHead = tdp;
1036  tdp->link_pad = LSW(dp->tdaTail) | TDA_LINK_EOL;
1037  tdp->next = (TransmitDescriptor_t *)dp->tdaTail;
1038  tdp->linkp = &dp->tdaTail->frag[0].frag_link;
1039
1040  /*
1041   *  Set up circular linked list in Receive Descriptor Area.
1042   *  Leaves dp->rda pointing at the `beginning' of the list.
1043   *
1044   *  NOTE: The RDA and CDP must have the same MSW for their addresses.
1045   */
1046
1047  dp->rda = sonic_allocate(
1048              (dp->rdaCount * sizeof(ReceiveDescriptor_t)) +
1049                sizeof(CamDescriptor_t) );
1050  dp->cdp = (CamDescriptorPointer_t) ((unsigned char *)dp->rda +
1051        (dp->rdaCount * sizeof(ReceiveDescriptor_t)));
1052#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
1053  printf( "rda area = %p\n", dp->rda );
1054  printf( "cdp area = %p\n", dp->cdp );
1055#endif
1056
1057  ordp = rdp = dp->rda;
1058  for (i = 0 ; i < dp->rdaCount ; i++) {
1059    /*
1060     *  status, byte_count, pkt_ptr0, pkt_ptr1, and seq_no are set
1061     *  to zero by sonic_allocate.
1062     */
1063    rdp->link   = LSW(rdp + 1);
1064    rdp->in_use = RDA_FREE;
1065    rdp->next   = (ReceiveDescriptor_t *)(rdp + 1);
1066    ordp = rdp;
1067    rdp++;
1068  }
1069  /*
1070   *  Link the last desriptor to the 1st one and mark it as the end
1071   *  of the list.
1072   */
1073  ordp->next   = dp->rda;
1074  ordp->link   = LSW(dp->rda) | RDA_LINK_EOL;
1075  dp->rdp_last = rdp;
1076 
1077  /*
1078   * Allocate the receive resource area.
1079   * In accordance with National Application Note 746, make the
1080   * receive resource area bigger than the receive descriptor area.
1081   * This has the useful side effect of making the receive resource
1082   * area big enough to hold the CAM descriptor area.
1083   */
1084
1085  dp->rsa = sonic_allocate((dp->rdaCount + RRA_EXTRA_COUNT) * sizeof *dp->rsa);
1086#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
1087  printf( "rsa area = %p\n", dp->rsa );
1088#endif
1089
1090  /*
1091   *  Set up list in Receive Resource Area.
1092   *  Allocate space for incoming packets.
1093   */
1094
1095  rwp = dp->rsa;
1096  for (i = 0 ; i < (dp->rdaCount + RRA_EXTRA_COUNT) ; i++, rwp++) {
1097    struct mbuf **mbp;
1098
1099    /*
1100     * Allocate memory for buffer.
1101     * Place a pointer to the mbuf at the beginning of the buffer
1102     * so we can find the mbuf when the SONIC returns the buffer
1103     * to the driver.
1104     */
1105    bp = ambufw (RBUF_SIZE);
1106    mbp = (struct mbuf **)bp->data;
1107    bp->data += sizeof *mbp;
1108    *mbp = bp;
1109
1110    /*
1111     * Set up RRA entry
1112     */
1113
1114    rwp->buff_ptr_lsw = LSW(bp->data);
1115    rwp->buff_ptr_msw = MSW(bp->data);
1116    rwp->buff_wc_lsw = RBUF_WC;
1117    rwp->buff_wc_msw = 0;
1118  }
1119  dp->rea = rwp;
1120#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
1121  printf( "rea area = %p\n", dp->rea );
1122#endif
1123
1124
1125  /*
1126   * Issue a software reset.
1127   */
1128  sonic_write_register( rp, SONIC_REG_CR, CR_RST | CR_STP | CR_RXDIS | CR_HTX );
1129
1130  /*
1131   * Set up data configuration registers.
1132   */
1133  sonic_write_register( rp, SONIC_REG_DCR, SONIC_DCR );
1134  sonic_write_register( rp, SONIC_REG_DCR2, SONIC_DC2 );
1135
1136  sonic_write_register( rp, SONIC_REG_CR, CR_STP | CR_RXDIS | CR_HTX );
1137
1138  /*
1139   * Mask all interrupts
1140   */
1141  sonic_write_register( rp, SONIC_REG_IMR, 0x3fff );
1142
1143  /*
1144   * Clear outstanding interrupts.
1145   */
1146  sonic_write_register( rp, SONIC_REG_ISR, 0x7FFF );
1147
1148  /*
1149   *  Clear the tally counters
1150   */
1151
1152  sonic_write_register( rp, SONIC_REG_CRCT, 0xFFFF );
1153  sonic_write_register( rp, SONIC_REG_FAET, 0xFFFF );
1154  sonic_write_register( rp, SONIC_REG_MPT, 0xFFFF );
1155  sonic_write_register( rp, SONIC_REG_RSC, 0 );
1156
1157  /*
1158   *  Set the Receiver mode
1159   *
1160   *  Enable/disable reception of broadcast packets
1161   */
1162
1163  if (broadcastFlag)
1164    sonic_write_register( rp, SONIC_REG_RCR, RCR_BRD );
1165  else
1166    sonic_write_register( rp, SONIC_REG_RCR, 0 );
1167
1168  /*
1169   * Set up Resource Area pointers
1170   */
1171
1172  sonic_write_register( rp, SONIC_REG_URRA, MSW(dp->rsa) );
1173  sonic_write_register( rp, SONIC_REG_RSA, LSW(dp->rsa) );
1174
1175  sonic_write_register( rp, SONIC_REG_REA, LSW(dp->rea) );
1176
1177  sonic_write_register( rp, SONIC_REG_RRP, LSW(dp->rsa) );
1178  sonic_write_register( rp, SONIC_REG_RWP, LSW(dp->rsa) ); /* XXX was rea */
1179
1180  sonic_write_register( rp, SONIC_REG_URDA, MSW(dp->rda) );
1181  sonic_write_register( rp, SONIC_REG_CRDA, LSW(dp->rda) );
1182
1183  sonic_write_register( rp, SONIC_REG_UTDA, MSW(dp->tdaTail) );
1184  sonic_write_register( rp, SONIC_REG_CTDA, LSW(dp->tdaTail) );
1185
1186  /*
1187   * Set End Of Buffer Count register to the value recommended
1188   * in Note 1 of Section 3.4.4.4 of the SONIC data sheet.
1189   */
1190
1191  sonic_write_register( rp, SONIC_REG_EOBC, RBUF_WC - 2 );
1192
1193  /*
1194   *  Issue the load RRA command
1195   */
1196
1197  sonic_write_register( rp, SONIC_REG_CR, CR_RRRA );
1198  while (sonic_read_register( rp, SONIC_REG_CR ) & CR_RRRA)
1199    continue;
1200
1201  /*
1202   * Remove device reset
1203   */
1204
1205  sonic_write_register( rp, SONIC_REG_CR, 0 );
1206
1207  /*
1208   *  Set up the SONIC CAM with our hardware address.
1209   */
1210
1211  hwaddr = dp->iface->hwaddr;
1212  cdp = dp->cdp;
1213
1214#if (SONIC_DEBUG & SONIC_DEBUG_CAM)
1215  printf( "hwaddr: %2x:%2x:%2x:%2x:%2x:%2x\n",
1216     hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5] );
1217#endif
1218
1219  cdp->cep  = 0;                     /* Fill first and only entry in CAM */
1220  cdp->cap0 = hwaddr[1] << 8 | hwaddr[0];
1221  cdp->cap1 = hwaddr[3] << 8 | hwaddr[2];
1222  cdp->cap2 = hwaddr[5] << 8 | hwaddr[4];
1223  cdp->ce   = 0x0001;                /* Enable first entry in CAM */
1224
1225  sonic_write_register( rp, SONIC_REG_CDC, 1 );      /* 1 entry in CDA */
1226  sonic_write_register( rp, SONIC_REG_CDP, LSW(cdp) );
1227  sonic_write_register( rp, SONIC_REG_CR,  CR_LCAM );  /* Load the CAM */
1228
1229  while (sonic_read_register( rp, SONIC_REG_CR ) & CR_LCAM)
1230    continue;
1231
1232  /*
1233   * Verify that CAM was properly loaded.
1234   */
1235
1236  sonic_write_register( rp, SONIC_REG_CR, CR_RST | CR_STP | CR_RXDIS | CR_HTX );
1237
1238#if (SONIC_DEBUG & SONIC_DEBUG_CAM)
1239  sonic_write_register( rp, SONIC_REG_CEP, 0 );  /* Select first entry in CAM */
1240    printf ("Loaded Ethernet address into SONIC CAM.\n"
1241      "  Wrote %04x%04x%04x - %#x\n"
1242      "   Read %04x%04x%04x - %#x\n",
1243        cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce,
1244        sonic_read_register( rp, SONIC_REG_CAP2 ),
1245        sonic_read_register( rp, SONIC_REG_CAP1 ),
1246        sonic_read_register( rp, SONIC_REG_CAP0 ),
1247        sonic_read_register( rp, SONIC_REG_CE ));
1248#endif
1249
1250  sonic_write_register( rp, SONIC_REG_CEP, 0 );  /* Select first entry in CAM */
1251  if ((sonic_read_register( rp, SONIC_REG_CAP2 ) != cdp->cap2)
1252   || (sonic_read_register( rp, SONIC_REG_CAP1 ) != cdp->cap1)
1253   || (sonic_read_register( rp, SONIC_REG_CAP0 ) != cdp->cap0)
1254   || (sonic_read_register( rp, SONIC_REG_CE ) != cdp->ce)) {
1255    printf ("Failed to load Ethernet address into SONIC CAM.\n"
1256      "  Wrote %04x%04x%04x - %#x\n"
1257      "   Read %04x%04x%04x - %#x\n",
1258        cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce,
1259        sonic_read_register( rp, SONIC_REG_CAP2 ),
1260        sonic_read_register( rp, SONIC_REG_CAP1 ),
1261        sonic_read_register( rp, SONIC_REG_CAP0 ),
1262        sonic_read_register( rp, SONIC_REG_CE ));
1263    rtems_panic ("SONIC LCAM");
1264  }
1265
1266  sonic_write_register(rp, SONIC_REG_CR, CR_TXP | CR_RXEN | CR_STP);
1267
1268  /*
1269   * Attach SONIC interrupt handler
1270   */
1271  sonic_write_register( rp, SONIC_REG_IMR, 0 );
1272  old_handler = set_vector(sonic_interrupt_handler, dp->vector, 0);
1273
1274  /*
1275   * Remainder of hardware initialization is
1276   * done by the receive and transmit daemons.
1277   */
1278}
1279
1280/*
1281 * Attach an SONIC driver to the system
1282 * This is the only `extern' function in the driver.
1283 *
1284 * argv[0]: interface label, e.g. "rtems"
1285 * The remainder of the arguments are optional key/value pairs:
1286 * mtu ##                  --  maximum transmission unit, default 1500
1287 * broadcast y/n           -- accept or ignore broadcast packets, default yes
1288 * rbuf ##                 -- Set number of receive descriptor entries
1289 * tbuf ##                 -- Set number of transmit descriptor entries
1290 * ip ###.###.###.###      -- IP address
1291 * ether ##:##:##:##:##:## -- Ethernet address
1292 * reg ######              -- Address of SONIC device registers
1293 * vector ###              -- SONIC interrupt vector
1294 */
1295int
1296rtems_ka9q_driver_attach (int argc, char *argv[], void *p)
1297{
1298  struct sonic *dp;
1299  struct iface *iface;
1300  char *cp;
1301  int argIndex;
1302  int broadcastFlag;
1303  char cbuf[30];
1304
1305  /*
1306   * Find an unused entry
1307   */
1308  dp = sonic;
1309  for (;;) {
1310    if (dp == &sonic[NSONIC]) {
1311      printf ("No more SONIC devices.\n");
1312      return -1;
1313    }
1314    if (dp->iface == NULL)
1315      break;
1316    dp++;
1317  }
1318  if (if_lookup (argv[0]) != NULL) {
1319    printf ("Interface %s already exists\n", argv[0]);
1320    return -1;
1321  }
1322
1323  /*
1324   *  zero out the control structure
1325   */
1326
1327  memset( dp, 0, sizeof(struct sonic) );
1328
1329  /*
1330   * Create an inteface descriptor
1331   */
1332  iface = callocw (1, sizeof *iface);
1333  iface->name = strdup (argv[0]);
1334  iface->dev = dp - sonic;
1335
1336  /*
1337   * Set default values
1338   */
1339  broadcastFlag = 1;
1340  dp->txWaitTid = 0;
1341  dp->rdaCount = RDA_COUNT;
1342  dp->tdaCount = TDA_COUNT;
1343  iface->mtu = 1500;
1344  iface->addr = Ip_addr;
1345  iface->hwaddr = mallocw (EADDR_LEN);
1346  memset (iface->hwaddr, 0x08, EADDR_LEN);
1347  dp->sonic = (struct SonicRegisters *)SONIC_BASE_ADDRESS;
1348  dp->vector = SONIC_VECTOR;
1349
1350  /*
1351   * Parse remaining arguments
1352   */
1353  for (argIndex = 1 ; argIndex < (argc - 1) ; argIndex++) {
1354    if (strcmp ("mtu", argv[argIndex]) == 0) {
1355      iface->mtu = strtoul (argv[++argIndex], NULL, 0);
1356    }
1357    else if (strcmp ("broadcast", argv[argIndex]) == 0) {
1358      if (*argv[++argIndex] == 'n')
1359        broadcastFlag = 0;
1360    }
1361    else if (strcmp ("rbuf", argv[argIndex]) == 0) {
1362      /*
1363       * The minimum RDA count is 2.  A single-entry RDA
1364       * would be difficult to use since the SONIC does
1365       * not release (in_use = 0) the RDA that has the
1366       * EOL bit set.
1367       */
1368      dp->rdaCount = strtoul (argv[++argIndex], NULL, 0);
1369      if ((dp->rdaCount <= 1) || (dp->rdaCount > 200)) {
1370        printf ("RDA option (%d) is invalid.\n", dp->rdaCount);
1371        return -1;
1372      }
1373    }
1374    else if (strcmp ("tbuf", argv[argIndex]) == 0) {
1375      dp->tdaCount = strtoul (argv[++argIndex], NULL, 0);
1376      if ((dp->tdaCount <= 1) || (dp->tdaCount > 200)) {
1377        printf ("TDA option (%d) is invalid.\n", dp->tdaCount);
1378        return -1;
1379      }
1380    }
1381    else if (strcmp ("ip", argv[argIndex]) == 0) {
1382      iface->addr = resolve (argv[++argIndex]);
1383    }
1384    else if (strcmp ("ether", argv[argIndex]) == 0) {
1385      gether (iface->hwaddr, argv[++argIndex]);
1386    }
1387    else if (strcmp ("reg", argv[argIndex]) == 0) {
1388      dp->sonic = (struct SonicRegisters *)strtoul (argv[++argIndex], NULL, 0);
1389    }
1390    else if (strcmp ("vector", argv[argIndex]) == 0) {
1391      dp->vector = strtoul (argv[++argIndex], NULL, 0);
1392    }
1393    else {
1394      printf ("Argument %d (%s) is invalid.\n", argIndex, argv[argIndex]);
1395      return -1;
1396    }
1397  }
1398  printf ("Ethernet address: %s\n", pether (cbuf, iface->hwaddr));
1399  iface->raw = sonic_raw;
1400  iface->stop = sonic_stop;
1401  iface->show = sonic_show;
1402  dp->iface = iface;
1403  setencap (iface, "Ethernet");
1404
1405  /*
1406   * Set up SONIC hardware
1407   */
1408  sonic_initialize_hardware (dp, broadcastFlag);
1409
1410  /*
1411   * Chain onto list of interfaces
1412   */
1413  iface->next = Ifaces;
1414  Ifaces = iface;
1415
1416  /*
1417   * Start I/O daemons
1418   */
1419  cp = if_name (iface, " tx");
1420  iface->txproc = newproc (cp, 2048, if_tx, iface->dev, iface, NULL, 0);
1421  free (cp);
1422  cp = if_name (iface, " rx");
1423  iface->rxproc = newproc (cp, 2048, sonic_rx, iface->dev, iface, dp, 0);
1424  free (cp);
1425  return 0;
1426}
1427
1428#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS)
1429#include <stdio.h>
1430
1431char SONIC_Reg_name[64][6]= {
1432    "CR",         /* 0x00 */
1433    "DCR",        /* 0x01 */
1434    "RCR",        /* 0x02 */
1435    "TCR",        /* 0x03 */
1436    "IMR",        /* 0x04 */
1437    "ISR",        /* 0x05 */
1438    "UTDA",       /* 0x06 */
1439    "CTDA",       /* 0x07 */
1440    "0x08",       /* 0x08 */
1441    "0x09",       /* 0x09 */
1442    "0x0A",       /* 0x0A */
1443    "0x0B",       /* 0x0B */
1444    "0x0C",       /* 0x0C */
1445    "URDA",       /* 0x0D */
1446    "CRDA",       /* 0x0E */
1447    "0x0F",       /* 0x0F */
1448    "0x10",       /* 0x10 */
1449    "0x11",       /* 0x11 */
1450    "0x12",       /* 0x12 */
1451    "EOBC",       /* 0x13 */
1452    "URRA",       /* 0x14 */
1453    "RSA",        /* 0x15 */
1454    "REA",        /* 0x16 */
1455    "RRP",        /* 0x17 */
1456    "RWP",        /* 0x18 */
1457    "0x19",       /* 0x19 */
1458    "0x1A",       /* 0x1A */
1459    "0x1B",       /* 0x1B */
1460    "0x1C",       /* 0x1C */
1461    "0x0D",       /* 0x1D */
1462    "0x1E",       /* 0x1E */
1463    "0x1F",       /* 0x1F */
1464    "0x20",       /* 0x20 */
1465    "CEP",        /* 0x21 */
1466    "CAP2",       /* 0x22 */
1467    "CAP1",       /* 0x23 */
1468    "CAP0",       /* 0x24 */
1469    "CE",         /* 0x25 */
1470    "CDP",        /* 0x26 */
1471    "CDC",        /* 0x27 */
1472    "SR",         /* 0x28 */
1473    "WT0",        /* 0x29 */
1474    "WT1",        /* 0x2A */
1475    "RSC",        /* 0x2B */
1476    "CRCT",       /* 0x2C */
1477    "FAET",       /* 0x2D */
1478    "MPT",        /* 0x2E */
1479    "MDT",        /* 0x2F */
1480    "0x30",       /* 0x30 */
1481    "0x31",       /* 0x31 */
1482    "0x32",       /* 0x32 */
1483    "0x33",       /* 0x33 */
1484    "0x34",       /* 0x34 */
1485    "0x35",       /* 0x35 */
1486    "0x36",       /* 0x36 */
1487    "0x37",       /* 0x37 */
1488    "0x38",       /* 0x38 */
1489    "0x39",       /* 0x39 */
1490    "0x3A",       /* 0x3A */
1491    "0x3B",       /* 0x3B */
1492    "0x3C",       /* 0x3C */
1493    "0x3D",       /* 0x3D */
1494    "0x3E",       /* 0x3E */
1495    "DCR2"        /* 0x3F */
1496};
1497#endif
1498void sonic_write_register(
1499  void       *base,
1500  unsigned32  regno,
1501  unsigned32  value
1502)
1503{
1504  volatile unsigned32 *p = base;
1505
1506#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS)
1507  printf( "%p Write 0x%04x to %s (0x%02x)\n",
1508      &p[regno], value, SONIC_Reg_name[regno], regno );
1509  fflush( stdout );
1510#endif
1511  p[regno] = value;
1512}
1513
1514unsigned32 sonic_read_register(
1515  void       *base,
1516  unsigned32  regno
1517)
1518{
1519  volatile unsigned32 *p = base;
1520  unsigned32           value;
1521
1522  value = p[regno];
1523#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS)
1524  printf( "%p Read 0x%04x from %s (0x%02x)\n",
1525      &p[regno], value, SONIC_Reg_name[regno], regno );
1526  fflush( stdout );
1527#endif
1528  return value;
1529}
Note: See TracBrowser for help on using the repository browser.