📄 network.c
字号:
/* * Unmask TXB (buffer transmitted) and * TXE (transmitter error) events. */ m8xx.fec.ievent |= M8xx_FEC_IEVENT_TFINT; 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_LAST | M8xx_BD_TX_CRC; txBd->status = status; firstTxBd->status |= M8xx_BD_READY; m8xx.fec.x_des_active = 0x1000000; sc->txBdActiveCount += nAdded; } break; } txBd->status = status; txBd = sc->txBdBase + sc->txBdHead; }}/* * Driver transmit daemon */voidscc_txDaemon (void *arg){ struct m860_enet_struct *sc = (struct m860_enet_struct *)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; scc_sendpacket (ifp, m); } ifp->if_flags &= ~IFF_OACTIVE; }}voidfec_txDaemon (void *arg){ struct m860_enet_struct *sc = (struct m860_enet_struct *)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; fec_sendpacket (ifp, m); } ifp->if_flags &= ~IFF_OACTIVE; }}/* * Send packet (caller provides header). */static voidm860_enet_start (struct ifnet *ifp){ struct m860_enet_struct *sc = ifp->if_softc; rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); ifp->if_flags |= IFF_OACTIVE;}/* * Initialize and start the device */static voidscc_init (void *arg){ struct m860_enet_struct *sc = arg; struct ifnet *ifp = &sc->arpcom.ac_if; if (sc->txDaemonTid == 0) { /* * Set up SCC hardware */ m860_scc_initialize_hardware (sc); /* * Start driver tasks */ sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, scc_txDaemon, sc); sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, scc_rxDaemon, sc); } /* * Set flags appropriately */ if (ifp->if_flags & IFF_PROMISC) m8xx.scc1.psmr |= 0x200; else m8xx.scc1.psmr &= ~0x200; /* * Tell the world that we're running. */ ifp->if_flags |= IFF_RUNNING; /* * Enable receiver and transmitter */ m8xx.scc1.gsmr_l |= 0x30;}static voidfec_init (void *arg){ struct m860_enet_struct *sc = arg; struct ifnet *ifp = &sc->arpcom.ac_if; if (sc->txDaemonTid == 0) { /* * Set up SCC hardware */ m860_fec_initialize_hardware (sc); /* * Start driver tasks */ sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, fec_txDaemon, sc); sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, fec_rxDaemon, sc); } /* * Set flags appropriately */ if (ifp->if_flags & IFF_PROMISC) m8xx.fec.r_cntrl |= 0x8; else m8xx.fec.r_cntrl &= ~0x8; /* * Tell the world that we're running. */ ifp->if_flags |= IFF_RUNNING; /* * Enable receiver and transmitter */ m8xx.fec.ecntrl = 0x2;}/* * Stop the device */static voidscc_stop (struct m860_enet_struct *sc){ struct ifnet *ifp = &sc->arpcom.ac_if; ifp->if_flags &= ~IFF_RUNNING; /* * Shut down receiver and transmitter */ m8xx.scc1.gsmr_l &= ~0x30;}static voidfec_stop (struct m860_enet_struct *sc){ struct ifnet *ifp = &sc->arpcom.ac_if; ifp->if_flags &= ~IFF_RUNNING; /* * Shut down receiver and transmitter */ m8xx.fec.ecntrl = 0x0;}/* * Show interface statistics */static voidenet_stats (struct m860_enet_struct *sc){ printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); printf (" Not First:%-8lu", sc->rxNotFirst); printf (" Not Last:%-8lu\n", sc->rxNotLast); printf (" Giant:%-8lu", sc->rxGiant); printf (" Runt:%-8lu", sc->rxRunt); printf (" Non-octet:%-8lu\n", sc->rxNonOctet); printf (" Bad CRC:%-8lu", sc->rxBadCRC); printf (" Overrun:%-8lu", sc->rxOverrun); printf (" Collision:%-8lu\n", sc->rxCollision); printf (" Discarded:%-8lu\n", (unsigned long)m8xx.scc1p.un.ethernet.disfc); printf (" Tx Interrupts:%-8lu", sc->txInterrupts); printf (" Deferred:%-8lu", sc->txDeferred); printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat); printf (" No Carrier:%-8lu", sc->txLostCarrier); printf ("Retransmit Limit:%-8lu", sc->txRetryLimit); printf (" Late Collision:%-8lu\n", sc->txLateCollision); printf (" Underrun:%-8lu", sc->txUnderrun); printf (" Raw output wait:%-8lu\n", sc->txRawWait);}/* * Driver ioctl handler */static intscc_ioctl (struct ifnet *ifp, int command, caddr_t data){ struct m860_enet_struct *sc = ifp->if_softc; int error = 0; switch (command) { case SIOCGIFADDR: case SIOCSIFADDR: ether_ioctl (ifp, command, data); break; case SIOCSIFFLAGS: switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { case IFF_RUNNING: scc_stop (sc); break; case IFF_UP: scc_init (sc); break; case IFF_UP | IFF_RUNNING: scc_stop (sc); scc_init (sc); break; default: break; } break; case SIO_RTEMS_SHOW_STATS: enet_stats (sc); break; /* * FIXME: All sorts of multicast commands need to be added here! */ default: error = EINVAL; break; } return error;}static intfec_ioctl (struct ifnet *ifp, int command, caddr_t data){ struct m860_enet_struct *sc = ifp->if_softc; int error = 0; switch (command) { case SIOCGIFADDR: case SIOCSIFADDR: ether_ioctl (ifp, command, data); break; case SIOCSIFFLAGS: switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { case IFF_RUNNING: fec_stop (sc); break; case IFF_UP: fec_init (sc); break; case IFF_UP | IFF_RUNNING: fec_stop (sc); fec_init (sc); break; default: break; } break; case SIO_RTEMS_SHOW_STATS: enet_stats (sc); break; /* * FIXME: All sorts of multicast commands need to be added here! */ default: error = EINVAL; break; } return error;}/* * Attach an SCC driver to the system */intrtems_scc1_driver_attach (struct rtems_bsdnet_ifconfig *config){ struct m860_enet_struct *sc; struct ifnet *ifp; int mtu; int i; /* * Find a free driver */ for (i = 0 ; i < NIFACES ; i++) { sc = &enet_driver[i]; ifp = &sc->arpcom.ac_if; if (ifp->if_softc == NULL) break; } if (i >= NIFACES) { printf ("Too many SCC drivers.\n"); return 0; } /* * Process options */ if (config->hardware_address) { memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); } else { sc->arpcom.ac_enaddr[0] = 0x44; sc->arpcom.ac_enaddr[1] = 0x22; sc->arpcom.ac_enaddr[2] = 0x33; sc->arpcom.ac_enaddr[3] = 0x33; sc->arpcom.ac_enaddr[4] = 0x22; sc->arpcom.ac_enaddr[5] = 0x44; } if (config->mtu) mtu = config->mtu; else mtu = ETHERMTU; if (config->rbuf_count) sc->rxBdCount = config->rbuf_count; else sc->rxBdCount = RX_BUF_COUNT; if (config->xbuf_count) sc->txBdCount = config->xbuf_count; else sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; sc->acceptBroadcast = !config->ignore_broadcast; /* * Set up network interface values */ ifp->if_softc = sc; ifp->if_unit = i + 1; ifp->if_name = "eth"; ifp->if_mtu = mtu; ifp->if_init = scc_init; ifp->if_ioctl = scc_ioctl; ifp->if_start = m860_enet_start; ifp->if_output = ether_output; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; if (ifp->if_snd.ifq_maxlen == 0) ifp->if_snd.ifq_maxlen = ifqmaxlen; /* * Attach the interface */ if_attach (ifp); ether_ifattach (ifp); return 1;};intrtems_fec_driver_attach (struct rtems_bsdnet_ifconfig *config){ struct m860_enet_struct *sc; struct ifnet *ifp; int mtu; /* * Find a free driver */ sc = &enet_driver[0]; ifp = &sc->arpcom.ac_if; if (ifp->if_softc != NULL) return 0; /* * Process options */ if (config->hardware_address) { memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); } else { sc->arpcom.ac_enaddr[0] = 0x44; sc->arpcom.ac_enaddr[1] = 0x22; sc->arpcom.ac_enaddr[2] = 0x33; sc->arpcom.ac_enaddr[3] = 0x33; sc->arpcom.ac_enaddr[4] = 0x22; sc->arpcom.ac_enaddr[5] = 0x44; } if (config->mtu) mtu = config->mtu; else mtu = ETHERMTU; if (config->rbuf_count) sc->rxBdCount = config->rbuf_count; else sc->rxBdCount = RX_BUF_COUNT; if (config->xbuf_count) sc->txBdCount = config->xbuf_count; else sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; sc->acceptBroadcast = !config->ignore_broadcast; /* * Set up network interface values */ ifp->if_softc = sc; ifp->if_unit = 1; ifp->if_name = "eth"; ifp->if_mtu = mtu; ifp->if_init = fec_init; ifp->if_ioctl = fec_ioctl; ifp->if_start = m860_enet_start; ifp->if_output = ether_output; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; if (ifp->if_snd.ifq_maxlen == 0) ifp->if_snd.ifq_maxlen = ifqmaxlen; /* * Attach the interface */ if_attach (ifp); ether_ifattach (ifp); return 1;};intrtems_enet_driver_attach (struct rtems_bsdnet_ifconfig *config){ if ((m8xx.fec.mii_data & 0xffff) == 0x2000) {/* rtems_scc1_driver_attach(config);*/ return rtems_fec_driver_attach(config); } else { return rtems_scc1_driver_attach(config); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -