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

📄 network.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
   * Set up receive buffer descriptors   */  for (i = 0 ; i < sc->rxBdCount ; i++)    (sc->rxBdBase + i)->status = 0;    /*   * Set up transmit buffer descriptors   */  for (i = 0 ; i < sc->txBdCount ; i++) {    (sc->txBdBase + i)->status = 0;    sc->txMbuf[i] = NULL;  }  sc->txBdHead = sc->txBdTail = 0;  sc->txBdActiveCount = 0;      /*   * Mask all FEC interrupts and clear events   */  m8xx.fec.imask = M8xx_FEC_IEVENT_TFINT |                    M8xx_FEC_IEVENT_RFINT;  m8xx.fec.ievent = ~0;  /*   * Set up interrupts   */  if (!BSP_install_rtems_irq_handler (&ethernetFECIrqData))    rtems_panic ("Can't attach M860 FEC interrupt handler\n", 0);}/* * Soak up buffer descriptors that have been sent * Note that a buffer descriptor can't be retired as soon as it becomes * ready.  The MC68360 Errata (May 96) says that, "If an Ethernet frame is *  made up of multiple buffers, the user should not reuse the first buffer * descriptor until the last buffer descriptor of the frame has had its * ready bit cleared by the CPM". */static voidm860Enet_retire_tx_bd (struct m860_enet_struct *sc){  rtems_unsigned16 status;  int i;  int nRetired;  struct mbuf *m, *n;    i = sc->txBdTail;  nRetired = 0;  while ((sc->txBdActiveCount != 0)         &&  (((status = (sc->txBdBase + i)->status) & M8xx_BD_READY) == 0)) {    /*     * See if anything went wrong     */    if (status & (M8xx_BD_DEFER |                  M8xx_BD_HEARTBEAT |                  M8xx_BD_LATE_COLLISION |                  M8xx_BD_RETRY_LIMIT |                  M8xx_BD_UNDERRUN |                  M8xx_BD_CARRIER_LOST)) {      /*       * Check for errors which stop the transmitter.       */      if (status & (M8xx_BD_LATE_COLLISION |                    M8xx_BD_RETRY_LIMIT |                    M8xx_BD_UNDERRUN)) {        if (status & M8xx_BD_LATE_COLLISION)          enet_driver[0].txLateCollision++;        if (status & M8xx_BD_RETRY_LIMIT)          enet_driver[0].txRetryLimit++;        if (status & M8xx_BD_UNDERRUN)          enet_driver[0].txUnderrun++;                /*         * Restart the transmitter         */        /* FIXME: this should get executed only if using the SCC */        m8xx_cp_execute_cmd (M8xx_CR_OP_RESTART_TX | M8xx_CR_CHAN_SCC1);      }      if (status & M8xx_BD_DEFER)        enet_driver[0].txDeferred++;      if (status & M8xx_BD_HEARTBEAT)        enet_driver[0].txHeartbeat++;      if (status & M8xx_BD_CARRIER_LOST)        enet_driver[0].txLostCarrier++;    }    nRetired++;    if (status & M8xx_BD_LAST) {      /*       * A full frame has been transmitted.       * Free all the associated buffer descriptors.       */      sc->txBdActiveCount -= nRetired;      while (nRetired) {        nRetired--;        m = sc->txMbuf[sc->txBdTail];        MFREE (m, n);        if (++sc->txBdTail == sc->txBdCount)          sc->txBdTail = 0;      }    }    if (++i == sc->txBdCount)      i = 0;  }}/* * reader task */static voidscc_rxDaemon (void *arg){  struct m860_enet_struct *sc = (struct m860_enet_struct *)arg;  struct ifnet *ifp = &sc->arpcom.ac_if;  struct mbuf *m;  rtems_unsigned16 status;  m8xxBufferDescriptor_t *rxBd;  int rxBdIndex;    /*   * Allocate space for incoming packets and start reception   */  for (rxBdIndex = 0 ; ;) {    rxBd = sc->rxBdBase + rxBdIndex;    MGETHDR (m, M_WAIT, MT_DATA);    MCLGET (m, M_WAIT);    m->m_pkthdr.rcvif = ifp;    sc->rxMbuf[rxBdIndex] = m;    rxBd->buffer = mtod (m, void *);    rxBd->status = M8xx_BD_EMPTY | M8xx_BD_INTERRUPT;    if (++rxBdIndex == sc->rxBdCount) {      rxBd->status |= M8xx_BD_WRAP;      break;    }  }    /*   * Input packet handling loop   */  rxBdIndex = 0;  for (;;) {    rxBd = sc->rxBdBase + rxBdIndex;        /*     * Wait for packet if there's not one ready     */    if ((status = rxBd->status) & M8xx_BD_EMPTY) {      /*       * Clear old events       */      m8xx.scc1.scce = 0x8;            /*       * Wait for packet       * Note that the buffer descriptor is checked       * *before* the event wait -- this catches the       * possibility that a packet arrived between the       * `if' above, and the clearing of the event register.       */      while ((status = rxBd->status) & M8xx_BD_EMPTY) {        rtems_event_set events;                /*         * Unmask RXF (Full frame received) event         */        m8xx.scc1.sccm |= 0x8;                rtems_bsdnet_event_receive (INTERRUPT_EVENT,                                    RTEMS_WAIT|RTEMS_EVENT_ANY,                                    RTEMS_NO_TIMEOUT,                                    &events);      }    }        /*     * Check that packet is valid     */    if ((status & (M8xx_BD_LAST |                   M8xx_BD_FIRST_IN_FRAME |                   M8xx_BD_LONG |                   M8xx_BD_NONALIGNED |                   M8xx_BD_SHORT |                   M8xx_BD_CRC_ERROR |                   M8xx_BD_OVERRUN |                   M8xx_BD_COLLISION)) ==        (M8xx_BD_LAST |         M8xx_BD_FIRST_IN_FRAME)) {      /*       * Pass the packet up the chain.       * FIXME: Packet filtering hook could be done here.       */      struct ether_header *eh;            m = sc->rxMbuf[rxBdIndex];      m->m_len = m->m_pkthdr.len = rxBd->length -        sizeof(rtems_unsigned32) -        sizeof(struct ether_header);      eh = mtod (m, struct ether_header *);      m->m_data += sizeof(struct ether_header);      ether_input (ifp, eh, m);            /*       * Allocate a new mbuf       */      MGETHDR (m, M_WAIT, MT_DATA);      MCLGET (m, M_WAIT);      m->m_pkthdr.rcvif = ifp;      sc->rxMbuf[rxBdIndex] = m;      rxBd->buffer = mtod (m, void *);    }    else {      /*       * Something went wrong with the reception       */      if (!(status & M8xx_BD_LAST))        sc->rxNotLast++;      if (!(status & M8xx_BD_FIRST_IN_FRAME))        sc->rxNotFirst++;      if (status & M8xx_BD_LONG)        sc->rxGiant++;      if (status & M8xx_BD_NONALIGNED)        sc->rxNonOctet++;      if (status & M8xx_BD_SHORT)        sc->rxRunt++;      if (status & M8xx_BD_CRC_ERROR)        sc->rxBadCRC++;      if (status & M8xx_BD_OVERRUN)        sc->rxOverrun++;      if (status & M8xx_BD_COLLISION)        sc->rxCollision++;    }        /*     * Reenable the buffer descriptor     */    rxBd->status = (status & (M8xx_BD_WRAP | M8xx_BD_INTERRUPT)) |                    M8xx_BD_EMPTY;        /*     * Move to next buffer descriptor     */    if (++rxBdIndex == sc->rxBdCount)      rxBdIndex = 0;  }}static voidfec_rxDaemon (void *arg){  struct m860_enet_struct *sc = (struct m860_enet_struct *)arg;  struct ifnet *ifp = &sc->arpcom.ac_if;  struct mbuf *m;  rtems_unsigned16 status;  m8xxBufferDescriptor_t *rxBd;  int rxBdIndex;    /*   * Allocate space for incoming packets and start reception   */  for (rxBdIndex = 0 ; ;) {    rxBd = sc->rxBdBase + rxBdIndex;    MGETHDR (m, M_WAIT, MT_DATA);    MCLGET (m, M_WAIT);    m->m_pkthdr.rcvif = ifp;    sc->rxMbuf[rxBdIndex] = m;    rxBd->buffer = mtod (m, void *);    rxBd->status = M8xx_BD_EMPTY;    m8xx.fec.r_des_active = 0x1000000;    if (++rxBdIndex == sc->rxBdCount) {      rxBd->status |= M8xx_BD_WRAP;      break;    }  }    /*   * Input packet handling loop   */  rxBdIndex = 0;  for (;;) {    rxBd = sc->rxBdBase + rxBdIndex;        /*     * Wait for packet if there's not one ready     */    if ((status = rxBd->status) & M8xx_BD_EMPTY) {      /*       * Clear old events       */      m8xx.fec.ievent = M8xx_FEC_IEVENT_RFINT;            /*       * Wait for packet       * Note that the buffer descriptor is checked       * *before* the event wait -- this catches the       * possibility that a packet arrived between the       * `if' above, and the clearing of the event register.       */      while ((status = rxBd->status) & M8xx_BD_EMPTY) {        rtems_event_set events;                /*         * Unmask RXF (Full frame received) event         */        m8xx.fec.ievent |= M8xx_FEC_IEVENT_RFINT;                rtems_bsdnet_event_receive (INTERRUPT_EVENT,                                    RTEMS_WAIT|RTEMS_EVENT_ANY,                                    RTEMS_NO_TIMEOUT,                                    &events);      }    }        /*     * Check that packet is valid     */    if (status & M8xx_BD_LAST) {      /*       * Pass the packet up the chain.       * FIXME: Packet filtering hook could be done here.       */      struct ether_header *eh;            m = sc->rxMbuf[rxBdIndex];      m->m_len = m->m_pkthdr.len = rxBd->length -        sizeof(rtems_unsigned32) -        sizeof(struct ether_header);      eh = mtod (m, struct ether_header *);      m->m_data += sizeof(struct ether_header);      ether_input (ifp, eh, m);            /*       * Allocate a new mbuf       */      MGETHDR (m, M_WAIT, MT_DATA);      MCLGET (m, M_WAIT);      m->m_pkthdr.rcvif = ifp;      sc->rxMbuf[rxBdIndex] = m;      rxBd->buffer = mtod (m, void *);    }    else {      /*       * Something went wrong with the reception       */      if (!(status & M8xx_BD_LAST))        sc->rxNotLast++;      if (status & M8xx_BD_LONG)        sc->rxGiant++;      if (status & M8xx_BD_NONALIGNED)        sc->rxNonOctet++;      if (status & M8xx_BD_SHORT)        sc->rxRunt++;      if (status & M8xx_BD_CRC_ERROR)        sc->rxBadCRC++;      if (status & M8xx_BD_OVERRUN)        sc->rxOverrun++;      if (status & M8xx_BD_COLLISION)        sc->rxCollision++;    }    /*     * Reenable the buffer descriptor     */    rxBd->status = (status & M8xx_BD_WRAP) |                    M8xx_BD_EMPTY;    m8xx.fec.r_des_active = 0x1000000;    /*     * Move to next buffer descriptor     */    if (++rxBdIndex == sc->rxBdCount)      rxBdIndex = 0;  }}static voidscc_sendpacket (struct ifnet *ifp, struct mbuf *m){  struct m860_enet_struct *sc = ifp->if_softc;  volatile m8xxBufferDescriptor_t *firstTxBd, *txBd;  struct mbuf *l = NULL;  rtems_unsigned16 status;  int nAdded;    /*   * Free up buffer descriptors   */  m860Enet_retire_tx_bd (sc);    /*   * Set up the transmit buffer descriptors.   * No need to pad out short packets since the   * hardware takes care of that automatically.   * No need to copy the packet to a contiguous buffer   * since the hardware is capable of scatter/gather DMA.   */  nAdded = 0;  txBd = firstTxBd = sc->txBdBase + sc->txBdHead;  for (;;) {    /*     * Wait for buffer descriptor to become available.     */    if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {      /*       * Clear old events       */      m8xx.scc1.scce = 0x12;            /*       * Wait for buffer descriptor to become available.       * Note that the buffer descriptors are checked       * *before* * entering the wait loop -- this catches       * the possibility that a buffer descriptor became       * available between the `if' above, and the clearing       * of the event register.       * This is to catch the case where the transmitter       * stops in the middle of a frame -- and only the       * last buffer descriptor in a frame can generate       * an interrupt.       */      m860Enet_retire_tx_bd (sc);      while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {        rtems_event_set events;                                        /*                                 * Unmask TXB (buffer transmitted) and                                 * TXE (transmitter error) events.                                 */        m8xx.scc1.sccm |= 0x12;        rtems_bsdnet_event_receive (INTERRUPT_EVENT,                                    RTEMS_WAIT|RTEMS_EVENT_ANY,                                    RTEMS_NO_TIMEOUT,                                    &events);        m860Enet_retire_tx_bd (sc);      }    }        /*     * Don't set the READY flag till the     * whole packet has been readied.     */    status = nAdded ? M8xx_BD_READY : 0;        /*     *  FIXME: Why not deal with empty mbufs at at higher level?     * The IP fragmentation routine in ip_output     * can produce packet fragments with zero length.     * I think that ip_output should be changed to get     * rid of these zero-length mbufs, but for now,     * I'll deal with them here.     */    if (m->m_len) {      /*       * Fill in the buffer descriptor       */      txBd->buffer = mtod (m, void *);      txBd->length = m->m_len;      sc->txMbuf[sc->txBdHead] = m;      nAdded++;      if (++sc->txBdHead == sc->txBdCount) {        status |= M8xx_BD_WRAP;        sc->txBdHead = 0;      }      l = m;      m = m->m_next;    }    else {      /*       * Just toss empty mbufs       */      struct mbuf *n;      MFREE (m, n);      m = n;      if (l != NULL)        l->m_next = m;    }        /*     * Set the transmit buffer status.     * Break out of the loop if this mbuf is the last in the frame.     */    if (m == NULL) {      if (nAdded) {        status |= M8xx_BD_PAD | M8xx_BD_LAST | M8xx_BD_TX_CRC | M8xx_BD_INTERRUPT;        txBd->status = status;        firstTxBd->status |= M8xx_BD_READY;        sc->txBdActiveCount += nAdded;      }      break;    }    txBd->status = status;    txBd = sc->txBdBase + sc->txBdHead;  }}static voidfec_sendpacket (struct ifnet *ifp, struct mbuf *m){  struct m860_enet_struct *sc = ifp->if_softc;  volatile m8xxBufferDescriptor_t *firstTxBd, *txBd;  /*  struct mbuf *l = NULL; */  rtems_unsigned16 status;  int nAdded;    /*   * Free up buffer descriptors   */  m860Enet_retire_tx_bd (sc);    /*   * Set up the transmit buffer descriptors.   * No need to pad out short packets since the   * hardware takes care of that automatically.   * No need to copy the packet to a contiguous buffer   * since the hardware is capable of scatter/gather DMA.   */  nAdded = 0;  txBd = firstTxBd = sc->txBdBase + sc->txBdHead;  for (;;) {    /*     * Wait for buffer descriptor to become available.     */    if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {      /*       * Clear old events       */      m8xx.fec.ievent = M8xx_FEC_IEVENT_TFINT;            /*       * Wait for buffer descriptor to become available.       * Note that the buffer descriptors are checked       * *before* * entering the wait loop -- this catches       * the possibility that a buffer descriptor became       * available between the `if' above, and the clearing       * of the event register.       * This is to catch the case where the transmitter       * stops in the middle of a frame -- and only the       * last buffer descriptor in a frame can generate       * an interrupt.       */      m860Enet_retire_tx_bd (sc);      while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {        rtems_event_set events;        

⌨️ 快捷键说明

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