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

📄 sonic.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
}/* * Send packet */SONIC_STATIC void sonic_sendpacket (struct ifnet *ifp, struct mbuf *m){  struct sonic_softc *sc = ifp->if_softc;  struct mbuf *l = NULL;  TransmitDescriptorPointer_t tdp;  volatile struct TransmitDescriptorFragLink *fp;  unsigned int packetSize;  int i;  rtems_event_set events;  static char padBuf[64];  /* printf( "sonic_sendpacket %p\n", m ); */  /*   * Wait for transmit descriptor to become available. Only retire TDA's   * if there are no more free buffers to minimize TX latency. Retire TDA'a   * on the way out.   */  while (sc->tdaHead->next->status != 0) {    /*   * Free up transmit descriptors   */    sonic_retire_tda (sc);    if (sc->tdaHead->next->status == 0)       break;#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)    printf("blocking until TDAs are available\n");#endif      /*       * Enable PINT interrupts.    sonic_clear_interrupts( sc, ISR_PINT );    sonic_enable_interrupts( sc, IMR_PINTEN );       */      /*       * Wait for PINT TX interrupt. Every fourth TX buffer will raise PINT.       */    rtems_bsdnet_event_receive (INTERRUPT_EVENT,            RTEMS_WAIT|RTEMS_EVENT_ANY,            RTEMS_NO_TIMEOUT,            &events);    sonic_disable_interrupts( sc, IMR_PINTEN );    sonic_retire_tda (sc);  }  /*   * Fill in the transmit descriptor fragment descriptors.   * ===CACHE===   * If data cache is operating in write-back mode, flush cached   * data to memory.   */  tdp = sc->tdaHead->next;  tdp->mbufp = m;  packetSize = 0;  fp = tdp->frag;  for (i = 0 ; i < MAXIMUM_FRAGS_PER_DESCRIPTOR ; i++, fp++) {    /*     * Throw away empty mbufs     */    if (m->m_len) {      void *p = mtod (m, void *);      fp->frag_lsw = LSW(p);      fp->frag_msw = MSW(p);      fp->frag_size = m->m_len;      packetSize += m->m_len;#if (SONIC_DEBUG & SONIC_DEBUG_FRAGMENTS)      printf( "fp %p 0x%04x%04x %d=%d .. %d\n",        fp, fp->frag_msw, fp->frag_lsw, fp->frag_size, m->m_len, packetSize );#endif#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_TX_MBUFS)      Dump_Buffer(        p,        (fp->frag_size > MAXIMUM_FRAME_SIZE) ? MAXIMUM_FRAME_SIZE : fp->frag_size      );#endif      l = m;      m = m->m_next;    }    else {      struct mbuf *n;      MFREE (m, n);      m = n;      if (l != NULL)        l->m_next = m;    }    /*     * Break out of the loop if this mbuf is the last in the frame.     */    if (m == NULL)      break;  }  /*   * Pad short packets.   */  if  ((packetSize < 64) && (i < MAXIMUM_FRAGS_PER_DESCRIPTOR)) {    int padSize = 64 - packetSize;    fp++;    fp->frag_lsw = LSW(padBuf);    fp->frag_msw = MSW(padBuf);    fp->frag_size = padSize;#if (SONIC_DEBUG & SONIC_DEBUG_FRAGMENTS)    printf( "PAD fp %p 0x%04x%04x %d\n",         fp, fp->frag_msw, fp->frag_lsw, fp->frag_size );#endif    packetSize += padSize;    i++;  }  /*   * Fill Transmit Descriptor   */  tdp->pkt_size = packetSize;  tdp->frag_count = i + 1;  tdp->status = 0;  /*   * Chain onto list and start transmission.   */  tdp->linkp = &(fp+1)->frag_link;  *tdp->linkp = LSW(tdp->next) | TDA_LINK_EOL;  if ( sc->tdaHead->frag_count )    *sc->tdaHead->linkp &= ~TDA_LINK_EOL;  sc->tdaHead = tdp;  /* Start transmission */  sonic_command(sc, CR_TXP );  /*   * Free up transmit descriptors on the way out.   */  sonic_retire_tda (sc);}/* * Driver transmit daemon */SONIC_STATIC void sonic_txDaemon (void *arg){  struct sonic_softc *sc = (struct sonic_softc *)arg;  struct ifnet *ifp = &sc->arpcom.ac_if;  struct mbuf *m;  rtems_event_set events;  for (;;) {    /*     * Wait for packet     */    rtems_bsdnet_event_receive (       START_TRANSMIT_EVENT,       RTEMS_EVENT_ANY | RTEMS_WAIT,       RTEMS_NO_TIMEOUT,       &events    );    /*     * Send packets till queue is empty     */    for (;;) {      /*       * Get the next mbuf chain to transmit.       */      IF_DEQUEUE(&ifp->if_snd, m);      if (!m)        break;      sonic_sendpacket (ifp, m);    }    ifp->if_flags &= ~IFF_OACTIVE;  }}/* ****************************************************************** *                                                                * *                        Receiver Routines                       * *                                                                * ****************************************************************** *//* * Wait for SONIC to hand over a Receive Descriptor. */SONIC_STATIC void sonic_rda_wait(  struct sonic_softc *sc,  ReceiveDescriptorPointer_t rdp){  int i;  void *rp = sc->sonic;  rtems_event_set events;  /*   * Wait for Receive Descriptor.   * The order of the tests is very important.   *    The RDA is checked after RBAE is detected.  This ensures that   *    the driver processes all RDA entries before reusing the RRA   *    entry holding the giant packet.   *    The event wait is done after the RDA and RBAE checks.  This   *    catches the possibility that a Receive Descriptor became ready   *    between the call to this function and the clearing of the   *    interrupt status register bit.   */  for (;;) {    /*     * Has a giant packet arrived?     * The National DP83932C data sheet is very vague on what     * happens under this condition.  The description of the     * Interrupt Status Register (Section 4.3.6) states,     * ``Reception is aborted and the SONIC fetches the next     * available resource descriptors in the RRA.  The buffer     * space is not re-used and an RDA is not setup for the     * truncated packet.''     * I take ``Reception is aborted''  to mean that the RXEN     * bit in the Command Register is cleared and must be set     * by the driver to begin reception again.     * Unfortunately, an alternative interpretation could be     * that only reception of the current packet is aborted.     * This would be more difficult to recover from....     */    if ((*sc->read_register)( rp, SONIC_REG_ISR ) & ISR_RBAE) {#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)      printf( "ERROR: looks like a giant packet -- RBAE\n" );#endif      /*       * One more check to soak up any Receive Descriptors       * that may already have been handed back to the driver.       */      if (rdp->in_use == RDA_IN_USE) {#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)      printf( "ERROR: nope just an RBAE\n" );#endif        break;      }      /*       * Check my interpretation of the SONIC manual.       */      if ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_RXEN)        rtems_panic ("SONIC RBAE/RXEN");      /*       * Update statistics       */      sc->rxGiant++;      /*       * Reuse receive buffer.       * Again, the manual is subject to interpretation.  The       * RRP register is described as, `the lower address of       * the next descriptor the SONIC will read.''       * Since, acording to the ISR/RBAE notes, the SONIC has       * ``fetched the next available resource descriptor in       * the RRA'', I interpret this to mean that that the       * driver has to move the RRP back *two* entries to       * reuse the receive buffer holding the giant packet.       */      for (i = 0 ; i < 2 ; i++) {        if ((*sc->read_register)( rp, SONIC_REG_RRP ) ==            (*sc->read_register)( rp, SONIC_REG_RSA ))          (*sc->write_register)(            rp,            SONIC_REG_RRP,            (*sc->read_register)( rp, SONIC_REG_REA )          );          (*sc->write_register)(             rp,             SONIC_REG_RRP,             (*sc->read_register)(rp, SONIC_REG_RRP) - sizeof(ReceiveResource_t)          );      }      /*       * Restart reception       */      sonic_clear_interrupts( sc, ISR_RBAE );      sonic_command( sc, CR_RXEN );    }    /*     * Has Receive Descriptor become available?     */    if (rdp->in_use == RDA_IN_USE)      break;    /*     * Enable interrupts.     */    sonic_enable_interrupts( sc, (IMR_PRXEN | IMR_RBAEEN) );    /*     * Wait for interrupt.     */    rtems_bsdnet_event_receive(      INTERRUPT_EVENT,      RTEMS_WAIT|RTEMS_EVENT_ANY,      RTEMS_NO_TIMEOUT,      &events    );  }#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)  printf( "RDA %p\n", rdp );#endif#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)    if (rdp->status & 0x000E)      printf( "ERROR: RDA %p (0x%04x)\n", rdp, rdp->status );#endif}#ifdef CPU_U32_FIX/* * Routine to align the received packet so that the ip header * is on a 32-bit boundary. Necessary for cpu's that do not * allow unaligned loads and stores and when the 32-bit DMA * mode is used.  *  * Transfers are done on word basis to avoid possibly slow byte  * and half-word writes. */ void ipalign(struct mbuf *m){  unsigned int *first, *last, data;  unsigned int tmp = 0;  if ((((int) m->m_data) & 2) && (m->m_len)) {    last = (unsigned int *) ((((int) m->m_data) + m->m_len + 8) & ~3);    first = (unsigned int *) (((int) m->m_data) & ~3);    tmp = *first << 16;    first++;    do {      data = *first;      *first = tmp | (data >> 16);      tmp = data << 16;      first++;    } while (first <= last);    m->m_data = (caddr_t)(((int) m->m_data) + 2);  }}#endif/* * SONIC reader task */SONIC_STATIC void sonic_rxDaemon (void *arg){  struct sonic_softc *sc = (struct sonic_softc *)arg;  struct ifnet *ifp = &sc->arpcom.ac_if;  void *rp = sc->sonic;  struct mbuf *m;  rtems_unsigned16 status;  ReceiveDescriptorPointer_t rdp;  ReceiveResourcePointer_t rwp, rea;  rtems_unsigned16 newMissedTally, oldMissedTally;  rwp = sc->rsa;  rea = sc->rea;  rdp = sc->rda;  /*   * Start the receiver   */  oldMissedTally = (*sc->read_register)( rp, SONIC_REG_MPT );  /*   * Input packet handling loop   */  for (;;) {    /*     * Wait till SONIC supplies a Receive Descriptor.     */    if (rdp->in_use == RDA_FREE) {      sonic_rda_wait (sc, rdp);    }#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)    printf( "Incoming packet %p status=0x%04x\n", rdp, rdp->status );#endif    /*     * Check that packet is valid     */    status = rdp->status;    if (status & RDA_STATUS_PRX) {      struct ether_header *eh;      void *p;      /*       * Pass the packet up the chain.       * The mbuf count is reduced to remove       * the frame check sequence at the end       * of the packet.       * ===CACHE===       * Invalidate cache entries for this memory.       */#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS)      sonic_print_rx_descriptor( rdp );      if ((LSW(rdp->mbufp->m_data) != rdp->pkt_lsw)       || (MSW(rdp->mbufp->m_data) != rdp->pkt_msw))        printf ("SONIC RDA/RRA %p, %08x\n",rdp->mbufp->m_data,(rdp->pkt_msw << 16) | 	(rdp->pkt_lsw & 0x0ffff));#endif      rdp->byte_count &= 0x0ffff;    /* ERC32 pollutes msb of byte_count */      m = rdp->mbufp;      m->m_len = m->m_pkthdr.len = rdp->byte_count -                          sizeof(rtems_unsigned32) -                          sizeof(struct ether_header);      eh = mtod (m, struct ether_header *);      m->m_data += sizeof(struct ether_header);  #ifdef CPU_U32_FIX      ipalign(m);	/* Align packet on 32-bit boundary */#endif#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_RX_MBUFS)      Dump_Buffer( (void *) eh, sizeof(struct ether_header) );      Dump_Buffer( (void *) m, 96 /* m->m_len*/ );#endif      /* printf( "ether_input %p\n", m ); */      /*      printf( "pkt %p, seq %04x, mbuf %p, m_data %p\n", rdp, rdp->seq_no, m, m->m_data );      printf( "%u, %u\n", ((int*)m->m_data)[6], ((int*)m->m_data)[7]);      */      ether_input (ifp, eh, m);      /*      */      /*       * Sanity check that Receive Resource Area is       * still in sync with Receive Descriptor Area       * The buffer reported in the Receive Descriptor       * should be the same as the buffer in the Receive       * Resource we are about to reuse.       *//* XXX figure out whether this is valid or not */#if 0      if ((LSW(p) != rwp->buff_ptr_lsw)       || (MSW(p) != rwp->buff_ptr_msw))        rtems_panic ("SONIC RDA/RRA");#endif      /*       * Allocate a new mbuf.       */      MGETHDR (m, M_WAIT, MT_DATA);      MCLGET (m, M_WAIT);      m->m_pkthdr.rcvif = ifp;      rdp->mbufp = m;      p = mtod (m, void *);      /*       * Reuse Receive Resource.       */      rwp->buff_ptr_lsw = LSW(p);      rwp->buff_ptr_msw = MSW(p);      rwp->buff_wc_lsw = RBUF_WC;      rwp->buff_wc_msw = 0;      rwp++;      if (rwp == rea) {#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)        printf( "Wrapping RWP from %p to %p\n", rwp, sc->rsa );#endif        rwp = sc->rsa;      }      (*sc->write_register)( rp, SONIC_REG_RWP , LSW(rwp) );      /*       * Tell the SONIC to reread the RRA.       */      if ((*sc->read_register)( rp, SONIC_REG_ISR ) & ISR_RBE)      sonic_clear_interrupts( sc, ISR_RBE );    }    else {      if (status & RDA_STATUS_COL)        sc->rxCollision++;      if (status & RDA_STATUS_FAER)        sc->rxNonOctet++;      else if (status & RDA_STATUS_CRCR)        sc->rxBadCRC++;    }    /*     * Count missed packets     */    newMissedTally = (*sc->read_register)( rp, SONIC_REG_MPT );    if (newMissedTally != oldMissedTally) {      sc->rxMissed += (newMissedTally - oldMissedTally) & 0xFFFF;      newMissedTally = oldMissedTally;    }    /*     * Move to next receive descriptor and update EOL     */    rdp->link |= RDA_LINK_EOL;    rdp->in_use = RDA_FREE;    sc->rdp_last->link &= ~RDA_LINK_EOL;    sc->rdp_last = rdp;    rdp = rdp->next;  }}/* ****************************************************************** *                                                                * *                     Initialization Routines                    * *                                                                * ****************************************************************** *//* * Initialize the SONIC hardware */SONIC_STATIC void sonic_initialize_hardware(struct sonic_softc *sc){  void *rp = sc->sonic;  int i;  unsigned char *hwaddr;  rtems_isr_entry old_handler;  TransmitDescriptorPointer_t tdp;  ReceiveDescriptorPointer_t ordp, rdp;  ReceiveResourcePointer_t rwp;  struct mbuf *m;  void *p;  CamDescriptorPointer_t cdp;  /*   *  The Revision B SONIC has a horrible bug known as the "Zero   *  Length Packet bug".  The initial board used to develop this   *  driver had a newer revision of the SONIC so there was no reason   *  to check for this.  If you have the Revision B SONIC chip, then   *  you need to add some code to the RX path to handle this weirdness.   */  if ( (*sc->read_register)( rp, SONIC_REG_SR ) <= SONIC_REVISION_B ) {    rtems_fatal_error_occurred( 0x0BADF00D );  /* don't eat this part :) */  }    /*   *  Set up circular linked list in Transmit Descriptor Area.   *  Use the PINT bit in the transmit configuration field to

⌨️ 快捷键说明

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