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

4.104.114.84.95
Last change on this file since 1253f39 was 1253f39, checked in by Joel Sherrill <joel.sherrill@…>, on 08/13/98 at 16:20:14

Cleaned up some debugging stuff.

Redid interrupt handler to read imr/isr once and to write the imr once.

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