📄 network.c
字号:
rtems_bsdnet_event_receive (INTERRUPT_EVENT, RTEMS_WAIT|RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &events);/* printk( "Rxd " ); */ } } /* * Check that packet is valid */ if ((status & (M8260_BD_LAST | M8260_BD_FIRST_IN_FRAME | M8260_BD_LONG | M8260_BD_NONALIGNED | M8260_BD_ABORT | M8260_BD_CRC_ERROR | M8260_BD_OVERRUN /*| M8260_BD_CARRIER_LOST*/)) == (M8260_BD_LAST | M8260_BD_FIRST_IN_FRAME ) ) {/* printk( "RxV " ); *//* * Invalidate the buffer for this descriptor */ rtems_cache_invalidate_multiple_data_lines((void *)rxBd->buffer, rxBd->length); m = sc->rxMbuf[rxBdIndex]; /* strip off HDLC CRC */ m->m_len = m->m_pkthdr.len = rxBd->length - sizeof(rtems_unsigned16); hdlc_input( ifp, 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 { printk( "RxErr[%04X,%d]", status, rxBd->length ); /* * Something went wrong with the reception */ if (!(status & M8260_BD_LAST)) sc->rxNotLast++; if (!(status & M8260_BD_FIRST_IN_FRAME)) sc->rxNotFirst++; if (status & M8260_BD_LONG) sc->rxGiant++; if (status & M8260_BD_NONALIGNED) sc->rxNonOctet++; if (status & M8260_BD_ABORT) sc->rxAbort++; if (status & M8260_BD_CRC_ERROR) sc->rxBadCRC++; if (status & M8260_BD_OVERRUN) sc->rxOverrun++; if (status & M8260_BD_CARRIER_LOST) sc->rxLostCarrier++; } /* * Reenable the buffer descriptor */ rxBd->status = (status & (M8260_BD_WRAP | M8260_BD_INTERRUPT)) | M8260_BD_EMPTY; /* * Move to next buffer descriptor */ if (++rxBdIndex == sc->rxBdCount) rxBdIndex = 0; }}static voidscc_sendpacket (struct ifnet *ifp, struct mbuf *m){ struct m8260_hdlc_struct *sc = ifp->if_softc; volatile m8260BufferDescriptor_t *firstTxBd, *txBd; struct mbuf *l = NULL; rtems_unsigned16 status; int nAdded; /* * Free up buffer descriptors */ m8260Enet_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;/* m8260.scc3.sccm |= (M8260_SCCE_TX | M8260_SCCE_TXE);*/ for (;;) { /* * Wait for buffer descriptor to become available. */ if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { /* * Clear old events */ m8260.scc3.scce = M8260_SCCE_TX | M8260_SCCE_TXE; /* * 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. */ m8260Enet_retire_tx_bd (sc); while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { rtems_event_set events; /* * Unmask TX (buffer transmitted) event */ m8260.scc3.sccm |= (M8260_SCCE_TX | M8260_SCCE_TXE); rtems_bsdnet_event_receive (INTERRUPT_EVENT, RTEMS_WAIT|RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &events); m8260Enet_retire_tx_bd (sc); } } /* * Don't set the READY flag till the * whole packet has been readied. */ status = nAdded ? M8260_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; /* * Flush the buffer for this descriptor */ rtems_cache_flush_multiple_data_lines((void *)txBd->buffer, txBd->length);/* throw off the header for Ethernet Emulation mode *//* txBd->buffer = mtod (m, void *); txBd->buffer += sizeof( struct ether_header ) + 2; txBd->length = m->m_len - sizeof( struct ether_header ) - 2;*/ sc->txMbuf[sc->txBdHead] = m; nAdded++; if (++sc->txBdHead == sc->txBdCount) { status |= M8260_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 |= M8260_BD_LAST | M8260_BD_TX_CRC | M8260_BD_INTERRUPT; txBd->status = status; firstTxBd->status |= M8260_BD_READY; sc->txBdActiveCount += nAdded; } break; } txBd->status = status; txBd = sc->txBdBase + sc->txBdHead; }}/* * Driver transmit daemon */voidscc_txDaemon (void *arg){ struct m8260_hdlc_struct *sc = (struct m8260_hdlc_struct *)arg; struct ifnet *ifp = &sc->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; }}/* * Send packet (caller provides header). */static voidm8260_hdlc_start (struct ifnet *ifp){ struct m8260_hdlc_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 m8260_hdlc_struct *sc = arg; struct ifnet *ifp = &sc->ac_if; if (sc->txDaemonTid == 0) { /* * Set up SCC hardware */ m8260_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); } #if 0 /* * Set flags appropriately */ if (ifp->if_flags & IFF_PROMISC) m8260.scc3.psmr |= 0x200; else m8260.scc3.psmr &= ~0x200;#endif /* * Tell the world that we're running. */ ifp->if_flags |= IFF_RUNNING; /* * Enable receiver and transmitter */ m8260.scc3.gsmr_l |= 0x30;}/* * Stop the device */static voidscc_stop (struct m8260_hdlc_struct *sc){ struct ifnet *ifp = &sc->ac_if; ifp->if_flags &= ~IFF_RUNNING; /* * Shut down receiver and transmitter */ m8260.scc3.gsmr_l &= ~0x30;}/* * Show interface statistics */static voidhdlc_stats (struct m8260_hdlc_struct *sc){ 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 (" Overrun:%-8lu", sc->rxOverrun); printf (" No Carrier:%-8lu\n", sc->rxLostCarrier); printf (" Discarded:%-8lu\n", (unsigned long)m8260.scc3p.un.hdlc.disfc); printf (" Tx Interrupts:%-8lu", sc->txInterrupts); printf (" No Carrier:%-8lu", sc->txLostCarrier); printf (" Underrun:%-8lu\n", 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 m8260_hdlc_struct *sc = ifp->if_softc; int error = 0; switch (command) { case SIOCGIFADDR: case SIOCSIFADDR: hdlc_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: hdlc_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_scc3_driver_attach (struct rtems_bsdnet_ifconfig *config){ struct m8260_hdlc_struct *sc; struct ifnet *ifp; int mtu; int i; /* * Find a free driver */ for (i = 0 ; i < NIFACES ; i++) { sc = &hdlc_driver[i]; ifp = &sc->ac_if; if (ifp->if_softc == NULL) break; } if (i >= NIFACES) { printf ("Too many SCC drivers.\n"); return 0; }#if 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; }#endif 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 = m8260_hdlc_start; ifp->if_output = hdlc_output; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | /*IFF_PROMISC |*/ IFF_NOARP; if (ifp->if_snd.ifq_maxlen == 0) ifp->if_snd.ifq_maxlen = ifqmaxlen; /* * Attach the interface */ if_attach (ifp); hdlc_ifattach (ifp); return 1;};intrtems_enet_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching){ return rtems_scc3_driver_attach( config );/* if ((m8260.fec.mii_data & 0xffff) == 0x2000) { return rtems_fec_driver_attach(config); } else { return rtems_scc1_driver_attach(config); }*/}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -