📄 open_eth.c
字号:
{ dp->rxMiss++; bad = 1; } if (len_status & OETH_RX_BD_LATECOL) { dp->rxCollision++; bad = 1; } if (!bad) { /* pass on the packet in the receive buffer */ len = len_status >> 16; m = (struct mbuf *) (dp->rxdesc[dp->rx_ptr].m); m->m_len = m->m_pkthdr.len = len - 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 ether_input (ifp, eh, m); /* get a new mbuf */ MGETHDR (m, M_WAIT, MT_DATA); MCLGET (m, M_WAIT); m->m_pkthdr.rcvif = ifp; dp->rxdesc[dp->rx_ptr].m = m; dp->regs->xd[dp->rx_ptr + dp->txbufs].addr = (unsigned32 *) mtod (m, void *); dp->rxPackets++; } dp->regs->xd[dp->rx_ptr+dp->txbufs].len_status = (dp->regs->xd[dp->rx_ptr+dp->txbufs].len_status & ~OETH_TX_BD_STATS) | OETH_TX_BD_READY; dp->rx_ptr = (dp->rx_ptr + 1) % dp->rxbufs; } }}static int inside = 0;static voidsendpacket (struct ifnet *ifp, struct mbuf *m){ struct open_eth_softc *dp = ifp->if_softc; unsigned char *temp; struct mbuf *n; unsigned int len, len_status; if (inside) printf ("error: sendpacket re-entered!!\n"); inside = 1; /* * Waiting for Transmitter ready */ n = m; while (dp->regs->xd[dp->tx_ptr].len_status & OETH_TX_BD_READY) {#ifdef OETH_SUSPEND_NOTXBUF rtems_event_set events; rtems_bsdnet_event_receive (OPEN_ETH_TX_WAIT_EVENT, RTEMS_WAIT | RTEMS_EVENT_ANY, TOD_MILLISECONDS_TO_TICKS(500), &events);#endif } len = 0; temp = (unsigned char *) dp->txdesc[dp->tx_ptr].buf; dp->regs->xd[dp->tx_ptr].addr = (unsigned32 *) temp;#ifdef OPEN_ETH_DEBUG printf("TXD: 0x%08x\n", (int) m->m_data);#endif for (;;) {#ifdef OPEN_ETH_DEBUG int i; printf("MBUF: 0x%08x : ", (int) m->m_data); for (i=0;i<m->m_len;i++) printf("%x%x", (m->m_data[i] >> 4) & 0x0ff, m->m_data[i] & 0x0ff); printf("\n");#endif len += m->m_len; if (len <= RBUF_SIZE) memcpy ((void *) temp, (char *) m->m_data, m->m_len); temp += m->m_len; if ((m = m->m_next) == NULL) break; } m_freem (n); /* don't send long packets */ if (len <= RBUF_SIZE) { /* Clear all of the status flags. */ len_status = dp->regs->xd[dp->tx_ptr].len_status & ~OETH_TX_BD_STATS; /* If the frame is short, tell CPM to pad it. */ if (len < ET_MINLEN) { len_status |= OETH_TX_BD_PAD; len = ET_MINLEN; } else len_status &= ~OETH_TX_BD_PAD; /* write buffer descriptor length and status */ len_status &= 0x0000ffff; len_status |= (len << 16) | (OETH_TX_BD_READY | OETH_TX_BD_CRC); dp->regs->xd[dp->tx_ptr].len_status = len_status; dp->tx_ptr = (dp->tx_ptr + 1) % dp->txbufs; } inside = 0;}/* * Driver transmit daemon */voidopen_eth_txDaemon (void *arg){ struct open_eth_softc *sc = (struct open_eth_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);#ifdef OPEN_ETH_DEBUG printf ("t\n");#endif /* * Send packets till queue is empty */ for (;;) { /* * Get the next mbuf chain to transmit. */ IF_DEQUEUE (&ifp->if_snd, m); if (!m) break; sendpacket (ifp, m); } ifp->if_flags &= ~IFF_OACTIVE; }}static voidopen_eth_start (struct ifnet *ifp){ struct open_eth_softc *sc = ifp->if_softc; rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); ifp->if_flags |= IFF_OACTIVE;}/* * Initialize and start the device */static voidopen_eth_init (void *arg){ struct open_eth_softc *sc = arg; struct ifnet *ifp = &sc->arpcom.ac_if; if (sc->txDaemonTid == 0) { /* * Set up OPEN_ETH hardware */ open_eth_initialize_hardware (sc); /* * Start driver tasks */ sc->rxDaemonTid = rtems_bsdnet_newproc ("DCrx", 4096, open_eth_rxDaemon, sc); sc->txDaemonTid = rtems_bsdnet_newproc ("DCtx", 4096, open_eth_txDaemon, sc); } /* * Tell the world that we're running. */ ifp->if_flags |= IFF_RUNNING;}/* * Stop the device */static voidopen_eth_stop (struct open_eth_softc *sc){ struct ifnet *ifp = &sc->arpcom.ac_if; ifp->if_flags &= ~IFF_RUNNING; sc->regs->moder = 0; /* RX/TX OFF */ sc->regs->moder = OETH_MODER_RST; /* Reset ON */ sc->regs->moder = 0; /* Reset OFF */}/* * Show interface statistics */static voidopen_eth_stats (struct open_eth_softc *sc){ printf (" Rx Packets:%-8lu", sc->rxPackets); printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); printf (" Length:%-8lu", sc->rxLengthError); printf (" Non-octet:%-8lu\n", sc->rxNonOctet); printf (" Bad CRC:%-8lu", sc->rxBadCRC); printf (" Overrun:%-8lu", sc->rxOverrun); printf (" Miss:%-8lu", sc->rxMiss); printf (" Collision:%-8lu\n", sc->rxCollision); 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 intopen_eth_ioctl (struct ifnet *ifp, int command, caddr_t data){ struct open_eth_softc *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: open_eth_stop (sc); break; case IFF_UP: open_eth_init (sc); break; case IFF_UP | IFF_RUNNING: open_eth_stop (sc); open_eth_init (sc); break; default: break; } break; case SIO_RTEMS_SHOW_STATS: open_eth_stats (sc); break; /* * FIXME: All sorts of multicast commands need to be added here! */ default: error = EINVAL; break; } return error;}/* * Attach an OPEN_ETH driver to the system */intrtems_open_eth_driver_attach (struct rtems_bsdnet_ifconfig *config, open_eth_configuration_t * chip){ struct open_eth_softc *sc; struct ifnet *ifp; int mtu; int unitNumber; char *unitName; /* parse driver name */ if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0) return 0; sc = &oc; ifp = &sc->arpcom.ac_if; memset (sc, 0, sizeof (*sc)); if (config->hardware_address) { memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); } else { memset (sc->arpcom.ac_enaddr, 0x08, ETHER_ADDR_LEN); } if (config->mtu) mtu = config->mtu; else mtu = ETHERMTU; sc->acceptBroadcast = !config->ignore_broadcast; sc->regs = (void *) chip->base_address; sc->vector = chip->vector; sc->txbufs = chip->txd_count; sc->rxbufs = chip->rxd_count; sc->en100MHz = chip->en100MHz; /* * Set up network interface values */ ifp->if_softc = sc; ifp->if_unit = unitNumber; ifp->if_name = unitName; ifp->if_mtu = mtu; ifp->if_init = open_eth_init; ifp->if_ioctl = open_eth_ioctl; ifp->if_start = open_eth_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);#ifdef OPEN_ETH_DEBUG printf ("OPEN_ETH : driver has been attached\n");#endif return 1;};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -