⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sonic.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *       RTEMS NETWORK DRIVER FOR NATIONAL DP83932 `SONIC' *         SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER * *                     REUSABLE CHIP DRIVER * * References: * *  1) DP83932C-20/25/33 MHz SONIC(TM) Systems-Oriented Network Interface *     Controller data sheet.  TL/F/10492, RRD-B30M105, National Semiconductor, *     1995. * *  2) Software Driver Programmer's Guide for the DP83932 SONIC(TM), *     Application Note 746, Wesley Lee and Mike Lui, TL/F/11140, *     RRD-B30M75, National Semiconductor, March, 1991. * *  COPYRIGHT (c) 1989-1997. *  On-Line Applications Research Corporation (OAR). * *  The license and distribution terms for this file may be *  found in the file LICENSE in this distribution or at *  http://www.rtems.com/license/LICENSE. * *  $Id: sonic.c,v 1.7.4.1 2003/09/04 18:46:04 joel Exp $ * *  This driver was originally written and tested on a DY-4 DMV177, *  which had a 100 Mhz PPC603e. * *  This driver also works with DP83934CVUL-20/25 MHz, tested on *  Tharsys ERC32 VME board.  * *  Rehaul to fix lost interrupts and buffers, and to use to use  *  interrupt-free transmission by Jiri, 22/03/1999. */#include <rtems.h>#include <rtems/rtems_bsdnet.h>#include <libchip/sonic.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <rtems/error.h>#include <sys/param.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/sockio.h>#include <sys/sockio.h>#include <net/if.h>#include <netinet/in.h>#include <netinet/if_ether.h>/* *  XXX fix this  */void *set_vector(void *, unsigned32, unsigned32);#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_MBUFS)#include <rtems/dumpbuf.h>#endif/* *  Use the top line if you want more symbols. */#define SONIC_STATIC /* #define SONIC_STATIC static *//* * Number of devices supported by this driver */#ifndef NSONIC# define NSONIC 1#endif/* *  * As suggested by National Application Note 746, make the * receive resource area bigger than the receive descriptor area. * * NOTE:  Changing this may break this driver since it currently *        assumes a 1<->1 mapping. */#define RRA_EXTRA_COUNT  0/* * RTEMS event used by interrupt handler to signal daemons. */#define INTERRUPT_EVENT  RTEMS_EVENT_1/* * RTEMS event used to start transmit daemon. * This must not be the same as INTERRUPT_EVENT. */#define START_TRANSMIT_EVENT    RTEMS_EVENT_2/* * Largest Ethernet frame. */#define MAXIMUM_FRAME_SIZE  1518/* * Receive buffer size. * Allow for a pointer, plus a full ethernet frame (including Frame * Check Sequence) rounded up to a 4-byte boundary. */#define RBUF_SIZE  ((sizeof (void *) + (MAXIMUM_FRAME_SIZE) + 3) & ~3)/* #define RBUF_WC    ((((MAXIMUM_FRAME_SIZE) + 3) & ~3) / 2) */#define RBUF_WC    (RBUF_SIZE / 2)/* * Macros for manipulating 32-bit pointers as 16-bit fragments */#define LSW(p)   ((rtems_unsigned16)((rtems_unsigned32)(p)))#define MSW(p)   ((rtems_unsigned16)((rtems_unsigned32)(p) >> 16))#define PTR(m,l) ((void*)(((rtems_unsigned16)(m)<<16)|(rtems_unsigned16)(l)))/* * Hardware-specific storage */struct sonic_softc {  /*   * Connection to networking code   * This entry *must* be the first in the sonic_softc structure.   */  struct arpcom                    arpcom;  /*   * Default location of device registers   * ===CACHE===   * This area must be non-cacheable, guarded.   */  void                             *sonic;  /*   *  Register access routines    */  sonic_write_register_t           write_register;  sonic_read_register_t            read_register;    /*   * Interrupt vector   */  rtems_vector_number             vector;  /*   * Data Configuration Register values   */  rtems_unsigned32                dcr_value;  rtems_unsigned32                dc2_value;  /*   *  Indicates configuration   */  int                             acceptBroadcast;  /*   * Task waiting for interrupts   */  rtems_id                        rxDaemonTid;  rtems_id                        txDaemonTid;  /*   * Receive resource area   */  int                             rdaCount;  ReceiveResourcePointer_t        rsa;  ReceiveResourcePointer_t        rea;  CamDescriptorPointer_t          cdp;  ReceiveDescriptorPointer_t      rda;  ReceiveDescriptorPointer_t      rdp_last;  /*   * Transmit descriptors   */  int                             tdaCount;  TransmitDescriptorPointer_t     tdaHead;  /* Last filled */  TransmitDescriptorPointer_t     tdaTail;  /* Next to retire */  /*   * Statistics   */  unsigned long                   Interrupts;  unsigned long                   rxInterrupts;  unsigned long                   rxMissed;  unsigned long                   rxGiant;  unsigned long                   rxNonOctet;  unsigned long                   rxBadCRC;  unsigned long                   rxCollision;  unsigned long                   txInterrupts;  unsigned long                   txSingleCollision;  unsigned long                   txMultipleCollision;  unsigned long                   txCollision;  unsigned long                   txDeferred;  unsigned long                   txUnderrun;  unsigned long                   txLateCollision;  unsigned long                   txExcessiveCollision;  unsigned long                   txExcessiveDeferral;  unsigned long                   txLostCarrier;  unsigned long                   txRawWait;};SONIC_STATIC struct sonic_softc sonic_softc[NSONIC];/* ****************************************************************** *                                                                * *                         Debug Routines                         * *                                                                * ****************************************************************** */#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS)void sonic_print_tx_descriptor(  TransmitDescriptorPointer_t tdp){  printf( "TXD ==> %p", tdp );  printf( "  pkt_config = 0x%04x", tdp->pkt_config & 0xffff);  printf( "  pkt_size = 0x%04x\n", tdp->pkt_size & 0xffff );  printf( "  frag_count = %d", tdp->frag_count & 0xffff );  /* could print all the fragments */  printf( "  next = %p", tdp->next );  printf( "  linkp = %p\n", tdp->linkp );  printf( "  mbufp = %p", tdp->mbufp );  if ( tdp->mbufp )    printf( "  mbufp->data = %p", mtod ( tdp->mbufp, void *) );  puts("");}void sonic_print_rx_descriptor(  ReceiveDescriptorPointer_t rdp){  printf( "RXD ==> %p\n", rdp );  printf( "  status = 0x%04x", rdp->status & 0xffff );  printf( "  byte_count = 0x%04x\n", rdp->byte_count & 0xffff );  printf( "  pkt = 0x%04x%04x", rdp->pkt_msw, rdp->pkt_lsw );  printf( "  seq_no = %d", rdp->seq_no );  printf( "  link = %d\n", rdp->link );  printf( "  in_use = %d", rdp->in_use );  printf( "  next = %p", rdp->next );  printf( "  mbufp = %p", rdp->mbufp );  if ( rdp->mbufp )    printf( "  mbufp->data = %p", mtod ( rdp->mbufp, void *) );  puts("");}#endif/* ****************************************************************** *                                                                * *                        Support Routines                        * *                                                                * ****************************************************************** */void sonic_enable_interrupts(  struct sonic_softc *sc,  unsigned32  mask){  void *rp = sc->sonic;  rtems_interrupt_level level;  rtems_interrupt_disable( level );      (*sc->write_register)(         rp,         SONIC_REG_IMR,         (*sc->read_register)(rp, SONIC_REG_IMR) | mask      );  rtems_interrupt_enable( level );}void sonic_disable_interrupts(  struct sonic_softc *sc,  unsigned32  mask){  void *rp = sc->sonic;  rtems_interrupt_level level;  rtems_interrupt_disable( level );  (*sc->write_register)(         rp,         SONIC_REG_IMR,         (*sc->read_register)(rp, SONIC_REG_IMR) & ~mask      );  rtems_interrupt_enable( level );}void sonic_clear_interrupts(  struct sonic_softc *sc,  unsigned32  mask){  void *rp = sc->sonic;  rtems_interrupt_level level;  rtems_interrupt_disable( level );  (*sc->write_register)( rp, SONIC_REG_ISR, mask);  rtems_interrupt_enable( level );}void sonic_command(  struct sonic_softc *sc,  unsigned32  mask){  void *rp = sc->sonic;  rtems_interrupt_level level;  rtems_interrupt_disable( level );  (*sc->write_register)( rp, SONIC_REG_CR, mask);  rtems_interrupt_enable( level );}/* * Allocate non-cacheable memory on a single 64k page. * Very simple minded -- just keeps trying till the memory is on a single page. */SONIC_STATIC void * sonic_allocate(unsigned int nbytes){  void *p;  unsigned long a1, a2;  for (;;) {    /*     * ===CACHE===     * Change malloc to malloc_noncacheable_guarded.     */    p = malloc( nbytes, M_MBUF, M_NOWAIT );    if (p == NULL)      rtems_panic ("No memory!");    memset (p, '\0', nbytes);    a1 = (unsigned long)p;    a2 = a1 + nbytes - 1;    if ((a1 >> 16) == (a2 >> 16))      break;  }#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_ALLOCATE)  printf( "sonic_allocate %d bytes at %p\n", nbytes, p );#endif  return p;}/* * Shut down the interface. */SONIC_STATIC void sonic_stop (struct sonic_softc *sc){  struct ifnet *ifp = &sc->arpcom.ac_if;  ifp->if_flags &= ~IFF_RUNNING;  /*   * Stop the transmitter and receiver.   */  sonic_command(sc, CR_HTX | CR_RXDIS );}/* * Show interface statistics */SONIC_STATIC void sonic_stats (struct sonic_softc *sc){  printf (" Total Interrupts:%-8lu", sc->Interrupts);  printf ("    Rx Interrupts:%-8lu", sc->rxInterrupts);  printf ("            Giant:%-8lu", sc->rxGiant);  printf ("        Non-octet:%-8lu\n", sc->rxNonOctet);  printf ("          Bad CRC:%-8lu", sc->rxBadCRC);  printf ("        Collision:%-8lu", sc->rxCollision);  printf ("           Missed:%-8lu\n", sc->rxMissed);  printf (    "    Tx Interrupts:%-8lu", sc->txInterrupts);  printf (  "           Deferred:%-8lu", sc->txDeferred);  printf ("        Lost Carrier:%-8lu\n", sc->txLostCarrier);  printf (   "Single Collisions:%-8lu", sc->txSingleCollision);  printf ( "Multiple Collisions:%-8lu", sc->txMultipleCollision);  printf ("Excessive Collisions:%-8lu\n", sc->txExcessiveCollision);  printf (   " Total Collisions:%-8lu", sc->txCollision);  printf ( "     Late Collision:%-8lu", sc->txLateCollision);  printf ("            Underrun:%-8lu\n", sc->txUnderrun);  printf (   "  Raw output wait:%-8lu\n", sc->txRawWait);}/* ****************************************************************** *                                                                * *                        Interrupt Handler                       * *                                                                * ****************************************************************** */SONIC_STATIC rtems_isr sonic_interrupt_handler (rtems_vector_number v){  struct sonic_softc *sc = sonic_softc;  unsigned32 isr, imr;  void *rp;#if (NSONIC > 1)  /*   * Find the device which requires service   */  for (;;) {    if (sc->vector == v)      break;    if (++sc == &sonic[NSONIC])      return;  /* Spurious interrupt? */  }#endif /* NSONIC > 1 */  /*   * Get pointer to SONIC registers   */  rp = sc->sonic;  sc->Interrupts++;  isr = (*sc->read_register)( rp, SONIC_REG_ISR );  imr = (*sc->read_register)( rp, SONIC_REG_IMR );  /*   * Packet received or receive buffer area exceeded?   */  if (imr & isr & (IMR_PRXEN | IMR_RBAEEN)) {    imr &= ~(IMR_PRXEN | IMR_RBAEEN);    sc->rxInterrupts++;    rtems_event_send (sc->rxDaemonTid, INTERRUPT_EVENT);    (*sc->write_register)( rp, SONIC_REG_IMR, imr );    (*sc->write_register)( rp, SONIC_REG_ISR, isr & ISR_PKTRX );  }  /*   * Packet started, transmitter done or transmitter error?   * TX interrupts only occur after an error or when all TDA's are   * exhausted and we are waiting for buffer to come free.   */  if (imr & isr & (IMR_PINTEN | IMR_TXEREN)) {    sc->txInterrupts++;    rtems_event_send (sc->txDaemonTid, INTERRUPT_EVENT);    (*sc->write_register)( rp, SONIC_REG_ISR, ISR_PINT | ISR_TXDN | ISR_TXER );  }}/* ****************************************************************** *                                                                * *                      Transmitter Routines                      * *                                                                * ****************************************************************** *//* * Soak up transmit descriptors that have been sent. */SONIC_STATIC void sonic_retire_tda (struct sonic_softc *sc){  rtems_unsigned16 status;  unsigned int collisions;  struct mbuf *m, *n;  /*   * Repeat for all completed transmit descriptors.   */  while ((status = sc->tdaTail->status) != 0) {#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)    printf( "retire TDA %p (0x%04x)\n", sc->tdaTail, status );#endif#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)    /*     *  If there is an error that was not a collision,      *  then someone may want to see it.     */    if ( (status & ~(TDA_STATUS_COLLISION_MASK|TDA_STATUS_DEF)) != 0x0001 )      printf( "ERROR: retire TDA %p (0x%08x)\n",                sc->tdaTail, sc->tdaTail->status );#endif    /*     * Check for errors which stop the transmitter.     */    if (status & (TDA_STATUS_EXD |        TDA_STATUS_EXC |        TDA_STATUS_FU |        TDA_STATUS_BCM)) {      /*       * Restart the transmitter if there are       * packets waiting to go.       */      rtems_unsigned16 link;#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)      printf("restarting sonic after error\n");#endif      link = *(sc->tdaTail->linkp);      if ((link & TDA_LINK_EOL) == 0) {        void *rp = sc->sonic;        (*sc->write_register)( rp, SONIC_REG_CTDA, link );        sonic_command(sc, CR_TXP );      }    }    /*     * Update network statistics     */    collisions = (status & TDA_STATUS_COLLISION_MASK) >> TDA_STATUS_COLLISION_SHIFT;    if (collisions) {      if (collisions == 1)        sc->txSingleCollision++;      else        sc->txMultipleCollision++;      sc->txCollision += collisions;    }    if (status & TDA_STATUS_EXC)      sc->txExcessiveCollision++;    if (status & TDA_STATUS_OWC)      sc->txLateCollision++;    if (status & TDA_STATUS_EXD)      sc->txExcessiveDeferral++;    if (status & TDA_STATUS_DEF)      sc->txDeferred++;    if (status & TDA_STATUS_FU)      sc->txUnderrun++;    if (status & TDA_STATUS_CRSL)      sc->txLostCarrier++;    /*     *  Free the packet and reset a couple of fields     */    m = sc->tdaTail->mbufp;    while ( m ) {      MFREE(m, n);      m = n;    }    /*    sc->tdaTail->frag[0].frag_link = LSW(sc->tdaTail->link_pad);    sc->tdaTail->frag_count        = 0;    */    sc->tdaTail->status        = 0;    /*     * Move to the next transmit descriptor     */    sc->tdaTail = sc->tdaTail->next;#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)    printf( "next TDA %p\n", sc->tdaTail );#endif  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -