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

4.104.114.84.95
Last change on this file since d4bf16c was dddc0557, checked in by Joel Sherrill <joel.sherrill@…>, on 08/05/98 at 23:56:13

DCR setting changed to match what the DY-4 Firmware initialized it to.
This primarily included setting the state of the programmable outputs
and the RX and TX FIFO depths.

Moved all of the TX, RX, and RRA data structure initialization to before
the hardware initialization. As part of this, the hardware initialization
was consolidated. More than likely, some of this movement broke stuff.

Used constants added to sonic.h which gave more logical names to some
of the register bit settings.

Switched to calloc to insure the data areas where initialized to 0.

Commented out a panic check in the RX server which may or may not have
been right.

Increased the size of the CAM initialization area. It is possible
that this could be decreased or code added to handle the management
of multiple hardware addresses.

Added sonic read and write register routines which aid greatly in
debugging and provide the core for the eventual movement of this
driver to libchip.

Added debug code to the read and write register routines which can
print the value read from or written to a register. This code also
prints the register name which significantly eases reading the log.

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