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

📄 network.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
		else {			/*			 * Something went wrong with the reception			 */			if (!(status & BUF_STAT_LAST))				sc->rxNotLast++;			if (!(status & BUF_STAT_FIRST_IN_FRAME))				sc->rxNotFirst++;			if (status & BUF_STAT_LONG)				sc->rxGiant++;			if (status & BUF_STAT_NONALIGNED)				sc->rxNonOctet++;			if (status & BUF_STAT_SHORT)				sc->rxRunt++;			if (status & BUF_STAT_CRC_ERROR)				sc->rxBadCRC++;			if (status & BUF_STAT_OVERRUN)				sc->rxOverrun++;			if (status & BUF_STAT_COLLISION)				sc->rxCollision++;		}		/*		 * Reenable the buffer descriptor		 */		rxBd->stat_ctrl = (status & (BUF_STAT_WRAP | BUF_STAT_INTERRUPT)) | BUF_STAT_EMPTY;		/*		 * Move to next buffer descriptor		 */		if (++rxBdIndex == sc->rxBdCount)			rxBdIndex = 0;	}}static voidsendpacket (struct ifnet *ifp, struct mbuf *m){	struct scc_softc *sc = ifp->if_softc;	volatile struct m68302_scc_bd *firstTxBd, *txBd;	struct mbuf *l = NULL;	rtems_unsigned16 status;	int nAdded;		/*	 * Free up buffer descriptors	 */	m302Enet_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.	 */	status = 0;	nAdded = 0;	txBd = firstTxBd = sc->txBdBase + sc->txBdHead;	while (m) {		/*		 * There are more mbufs in the packet than there		 * are transmit buffer descriptors.		 * Coalesce into a single buffer.		 */		if (nAdded == sc->txBdCount) {			struct mbuf *nm;			int j;			char *dest;			/*			 * Get the pointer to the first mbuf of the packet			 */			if (sc->txBdTail != sc->txBdHead)				rtems_panic ("sendpacket coalesce");			m = sc->txMbuf[sc->txBdTail];			/*			 * Rescind the buffer descriptor READY bits			 */			for (j = 0 ; j < sc->txBdCount ; j++)				(sc->txBdBase + j)->stat_ctrl = 0;			/*			 * Allocate an mbuf cluster			 * Toss the packet if allocation fails			 */			MGETHDR (nm, M_DONTWAIT, MT_DATA);			if (nm == NULL) {				sc->txCoalesceFailed++;				m_freem (m);
				return;			}			MCLGET (nm, M_DONTWAIT);			if (nm->m_ext.ext_buf == NULL) {				sc->txCoalesceFailed++;				m_freem (m);				m_free (nm);
				return;			}			nm->m_pkthdr = m->m_pkthdr;			nm->m_len = nm->m_pkthdr.len;			/*			 * Copy data from packet chain to mbuf cluster			 */			sc->txCoalesced++;			dest = nm->m_ext.ext_buf;			while (m) {				struct mbuf *n;				if (m->m_len) {					memcpy (dest, mtod(m, caddr_t), m->m_len);					dest += m->m_len;				}				MFREE (m, n);				m = n;			}						/*			 * Redo the send with the new mbuf cluster			 */			m = nm;			nAdded = 0;			status = 0;						continue;		}		/*		 * Wait for buffer descriptor to become available.		 */		if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {			/*			 * Clear old events			 */			M68en302imp_intr_event = INTR_EVENT_BIT_TFINT | INTR_EVENT_BIT_TXB;			/*			 * 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.			 */			m302Enet_retire_tx_bd (sc);			while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) {				rtems_interrupt_level level;				rtems_event_set events;				/*				 * Unmask TXB (buffer transmitted) and				 * TXE (transmitter error) events.				 */				rtems_interrupt_disable (level);				M68en302imp_intr_mask |= INTR_MASK_BIT_TFIEN | INTR_MASK_BIT_TXIEN;  				rtems_interrupt_enable (level);
				rtems_bsdnet_event_receive (INTERRUPT_EVENT,						RTEMS_WAIT|RTEMS_EVENT_ANY,						RTEMS_NO_TIMEOUT,						&events);				m302Enet_retire_tx_bd (sc);			}		}		/*		 * The IP fragmentation routine in ip_output		 * can produce packet fragments with zero length.		 */		if (m->m_len) {			/*			 * Fill in the buffer descriptor.			 * Don't set the READY flag in the first buffer			 * descriptor till the whole packet has been readied.			 */			txBd = sc->txBdBase + sc->txBdHead;			txBd->p_buffer = mtod (m, void *);			txBd->data_lgth = m->m_len;						sc->txMbuf[sc->txBdHead] = m;			status = nAdded ? BUF_STAT_READY : 0;			if (++sc->txBdHead == sc->txBdCount) {				status |= BUF_STAT_WRAP;				sc->txBdHead = 0;			}			txBd->stat_ctrl = status;			l = m;			m = m->m_next;			nAdded++;				}		else {			/*			 * Just toss empty mbufs			 */			struct mbuf *n;			MFREE (m, n);			m = n;			if (l != NULL)				l->m_next = m;				}	}	if (nAdded) {		/*		 * Send the packet		 */		txBd->stat_ctrl = status | BUF_STAT_LAST | BUF_STAT_TX_CRC | BUF_STAT_INTERRUPT;		firstTxBd->stat_ctrl |= BUF_STAT_READY;		sc->txBdActiveCount += nAdded;		}}/* * Driver transmit daemon */voidscc_txDaemon (void *arg){	struct scc_softc *sc = (struct scc_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;			sendpacket (ifp, m);		}		ifp->if_flags &= ~IFF_OACTIVE;	}}/* * Send packet (caller provides header). */static voidscc_start (struct ifnet *ifp){	struct scc_softc *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 scc_softc *sc = arg;	struct ifnet *ifp = &sc->arpcom.ac_if;	if (sc->txDaemonTid == 0) {		/*		 * Set up SCC hardware		 */		m302Enet_initialize_hardware (sc);
		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)		m360.scc1.psmr |= 0x200;	else		m360.scc1.psmr &= ~0x200;*/	/*	 * Tell the world that we're running.	 */	ifp->if_flags |= IFF_RUNNING;	/*	 * Enable receiver and transmitter	 */	M68en302imp_ecntrl = ECNTRL_BIT_RESET	| ECNTRL_BIT_ETHER_EN;	}/* * Stop the device */static voidscc_stop (struct scc_softc *sc){	struct ifnet *ifp = &sc->arpcom.ac_if;	ifp->if_flags &= ~IFF_RUNNING;	/*	 * Shut down receiver and transmitter	 */	M68en302imp_ecntrl &= ~(ECNTRL_BIT_RESET	| ECNTRL_BIT_ETHER_EN);}/* * Show interface statistics */static voidscc_stats (struct scc_softc *sc){	printf ("      Rx Interrupts:%-8lu", sc->rxInterrupts);	printf ("       Not First:%-8lu", sc->rxNotFirst);	printf ("        Not Last:%-8lu\r\n", sc->rxNotLast);	printf ("              Giant:%-8lu", sc->rxGiant);	printf ("            Runt:%-8lu", sc->rxRunt);	printf ("       Non-octet:%-8lu\r\n", sc->rxNonOctet);	printf ("            Bad CRC:%-8lu", sc->rxBadCRC);	printf ("         Overrun:%-8lu", sc->rxOverrun);	printf ("       Collision:%-8lu\r\n", sc->rxCollision);/*	printf ("          Discarded:%-8lu\r\n", (unsigned long)m360.scc1p.un.ethernet.disfc);*/	printf ("      Tx Interrupts:%-8lu", sc->txInterrupts);	printf ("        Deferred:%-8lu", sc->txDeferred);	printf (" Missed Hearbeat:%-8lu\r\n", sc->txHeartbeat);	printf ("         No Carrier:%-8lu", sc->txLostCarrier);	printf ("Retransmit Limit:%-8lu", sc->txRetryLimit);	printf ("  Late Collision:%-8lu\r\n", sc->txLateCollision);	printf ("           Underrun:%-8lu", sc->txUnderrun);	printf (" Raw output wait:%-8lu", sc->txRawWait);	printf ("       Coalesced:%-8lu\r\n", sc->txCoalesced);	printf ("    Coalesce failed:%-8lu", sc->txCoalesceFailed);	printf ("         Retries:%-8lu\r\n", sc->txRetry);}/* * Driver ioctl handler */static intscc_ioctl (struct ifnet *ifp, int command, caddr_t data){	struct scc_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:			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:		scc_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_ether1_driver_attach (struct rtems_bsdnet_ifconfig *config){	struct scc_softc *sc;	struct ifnet *ifp;	int mtu;	int unitNumber;	char *unitName;	a_m68302_imp = (struct m68302_imp *)0x700000L;	/* 	 * Parse driver name	 */	if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0)		return 0;		/*	 * Is driver free?	 */	if ((unitNumber <= 0) || (unitNumber > NSCCDRIVER)) {		printf ("Bad SCC unit number.\r\n");		return 0;	}	sc = &scc_softc[unitNumber - 1];	ifp = &sc->arpcom.ac_if;	if (ifp->if_softc != NULL) {		printf ("Driver already in use.\r\n");		return 0;	}	/*	 * Process options	 */	if (config->hardware_address) {		memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);	}		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;	sc->acceptBroadcast = !config->ignore_broadcast;	/*	 * Set up network interface values	 */	ifp->if_softc = sc;	ifp->if_unit = unitNumber;	ifp->if_name = unitName;	ifp->if_mtu = mtu;	ifp->if_init = scc_init;	ifp->if_ioctl = scc_ioctl;	ifp->if_start = scc_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;};

⌨️ 快捷键说明

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