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

4.104.114.84.95
Last change on this file since e70a8f16 was e70a8f16, checked in by Joel Sherrill <joel.sherrill@…>, on 08/06/98 at 19:01:02

Enabled specific types of debug info.

Added pointer to RDA to sonic structure.

Added macro names for values used in the in_use field of RDA entries.

Rewrote the RX Descriptor Area initialization loop.

Added a check to barf if this is a Rev B sonic chip.

Enabled check that the CAM was properly loaded.

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