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

4.104.114.84.95
Last change on this file since 301a2a3c was 301a2a3c, checked in by Joel Sherrill <joel.sherrill@…>, on 08/08/98 at 16:37:25

Changed debug level.

Moved CAM Descriptor types to sonic.h.

CAM memory is now malloced to insure it shares the same upper address bits.

Removed increment of RX interrupt count on TX interrupt path.

Added SONIC_DEBUG_FRAGMENTS and SONIC_DEBUG_CAM conditionals.

Fixed bugs in fragment manipulation. First bug was that the pad overwrote
the last fragment. The second bug was that the link information overwrote
the size of the last fragment.

Rewrote initialization of TDA to simplify it.

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