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

4.104.114.84.95
Last change on this file since c153a7b was c153a7b, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 10, 1998 at 9:27:33 PM

replies to ping -- forced into prosmiscuous mode

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