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

📄 if_tx.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
#else			ifp->if_flags |= IFF_LINK2;#endif		} else {			printf(", 10Mbps ");#if !defined(EPIC_NOIFMEDIA)			tmp |= IFM_10_T;#endif		}		if( i & BMCR_FULL_DUPLEX ) {			printf("FD");#if !defined(EPIC_NOIFMEDIA)			tmp |= IFM_FDX;#else			ifp->if_flags |= IFF_LINK1;#endif		}	}	/* Init ifmedia interface */#if !defined(EPIC_NOIFMEDIA)	ifmedia_init(&sc->ifmedia,0,epic_ifmedia_change,epic_ifmedia_status);	for (i=0; i<EPIC_MTYPESNUM; i++)		ifmedia_add(&sc->ifmedia,epic_mtypes[i],0,NULL);	ifmedia_set(&sc->ifmedia, tmp);#endif	s = splimp();	/* Map interrupt */	if( !pci_map_int(config_id, epic_intr, (void*)sc, &net_imask) ) {		printf(": couldn't map interrupt\n");		free(sc, M_DEVBUF);		return;	}	/* Set shut down routine to stop DMA processes on reboot */	at_shutdown(epic_shutdown, sc, SHUTDOWN_POST_SYNC);	/*  Attach to if manager */	if_attach(ifp);	ether_ifattach(ifp);#if NBPFILTER > 0	bpfattach(ifp,DLT_EN10MB, sizeof(struct ether_header));#endif	splx(s);	printf("\n");	return;}static voidepic_shutdown(    int howto,    void *sc){	epic_stop(sc);}#endif /* __OpenBSD__ *//* ------------------------------------------------------------------------   OS-independing part   ------------------------------------------------------------------------ *//* * This is if_ioctl handler.  */static intepic_ifioctl __P((    register struct ifnet * ifp,    EPIC_IFIOCTL_CMD_TYPE command,    caddr_t data)){	epic_softc_t *sc = ifp->if_softc;	int x, error = 0;	x = splimp();	switch (command) {#if defined(__FreeBSD__)	case SIOCSIFADDR:	case SIOCGIFADDR:	case SIOCSIFMTU:		error = ether_ioctl(ifp, command, data);		break;#else /* __OpenBSD__ */	case SIOCSIFADDR: {		struct ifaddr *ifa = (struct ifaddr *)data;				ifp->if_flags |= IFF_UP;		switch(ifa->ifa_addr->sa_family) {#if INET		case AF_INET:			epic_stop(sc);			epic_init(sc);			arp_ifinit(&sc->arpcom,ifa);			break;#endif /* __FreeBSD__ */#if NS		case AF_NS: {			register struct ns_addr * ina = &IA_SNS(ifa)->sns_addr;			if( ns_nullhost(*ina) ) 				ina->x_host = 				    *(union ns_host *) LLADDR(ifp->if_sadl);			else				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),				    ifp->if_addrlen);			epic_stop(sc);			epic_init(sc);			break;		}#endif		default:			epic_stop(sc);			epic_init(sc);					break;		}	}#endif	case SIOCSIFFLAGS:		/*		 * If the interface is marked up and stopped, then start it.		 * If it is marked down and running, then stop it.		 */		if (ifp->if_flags & IFF_UP) {			if ((ifp->if_flags & IFF_RUNNING) == 0) {				epic_init(sc);				break;			}		} else {			if (ifp->if_flags & IFF_RUNNING) {				epic_stop(sc);				break;			}		}		epic_stop_activity(sc);			/* Handle IFF_PROMISC flag */		epic_set_rx_mode(sc);#if defined(EPIC_NOIFMEDIA)		/* Handle IFF_LINKx flags */		epic_set_media_speed(sc);#endif		epic_start_activity(sc);			break;	case SIOCADDMULTI:	case SIOCDELMULTI:		/* Update out multicast list */#if defined(__FreeBSD__) && __FreeBSD_version >= 300000		epic_set_mc_table(sc);		error = 0;#else		error = (command == SIOCADDMULTI) ?		    ether_addmulti((struct ifreq *)data, &sc->arpcom) :		    ether_delmulti((struct ifreq *)data, &sc->arpcom);		if (error == ENETRESET) {			epic_set_mc_table(sc);			error = 0;		}#endif		break;#if !defined(EPIC_NOIFMEDIA)	case SIOCSIFMEDIA:	case SIOCGIFMEDIA:		error = ifmedia_ioctl(ifp, (struct ifreq *)data, 		    &sc->ifmedia, command);		break;#endif	default:		error = EINVAL;	}	splx(x);	return error;}/* * OS-independed part of attach process. allocate memory for descriptors * and frag lists, wake up chip, read MAC address and PHY identyfier. * Return -1 on failure. */static intepic_common_attach(    epic_softc_t *sc){	int i;	caddr_t pool;	i = sizeof(struct epic_frag_list)*TX_RING_SIZE +	    sizeof(struct epic_rx_desc)*RX_RING_SIZE + 	    sizeof(struct epic_tx_desc)*TX_RING_SIZE + PAGE_SIZE,	sc->pool = (epic_softc_t *) malloc( i, M_DEVBUF, M_NOWAIT);	if (sc->pool == NULL) {		printf(": can't allocate memory for buffers\n");		return -1;	}	bzero(sc->pool, i);	/* Align pool on PAGE_SIZE */	pool = (caddr_t)sc->pool;	pool = (caddr_t)((u_int32_t)(pool + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1));	/* Distribute memory */	sc->tx_flist = (void *)pool;	pool += sizeof(struct epic_frag_list)*TX_RING_SIZE;	sc->rx_desc = (void *)pool;	pool += sizeof(struct epic_rx_desc)*RX_RING_SIZE;	sc->tx_desc = (void *)pool;	/* Bring the chip out of low-power mode. */	CSR_WRITE_4( sc, GENCTL, 0x0000 );	/* Workaround for Application Note 7-15 */	for (i=0; i<16; i++) CSR_WRITE_4(sc, TEST1, TEST1_CLOCK_TEST);	/* Read mac address from EEPROM */	for (i = 0; i < ETHER_ADDR_LEN / sizeof(u_int16_t); i++)		((u_int16_t *)sc->sc_macaddr)[i] = epic_read_eeprom(sc,i);	/* Identify PHY */	sc->phyid = PHY_READ_2(sc, DP83840_PHYIDR1 )<<6;	sc->phyid|= (PHY_READ_2( sc, DP83840_PHYIDR2 )>>10)&0x3F;	if( QS6612_OUI != sc->phyid ) 		printf(": WARNING! PHY unknown (0x%x)",sc->phyid);	sc->tx_threshold = TRANSMIT_THRESHOLD;	sc->txcon = TXCON_DEFAULT;	return 0;}/* * This is if_start handler. It takes mbufs from if_snd queue * and quque them for transmit, one by one, until TX ring become full * or quque become empty. */static voidepic_ifstart(struct ifnet * const ifp){	epic_softc_t *sc = ifp->if_softc;	struct epic_tx_buffer *buf;	struct epic_tx_desc *desc;	struct epic_frag_list *flist;	struct mbuf *m0;	register struct mbuf *m;	register int i;#if 0	/* If no link is established, simply free all mbufs in queue */	PHY_READ_2( sc, DP83840_BMSR );	if( !(BMSR_LINK_STATUS & PHY_READ_2( sc, DP83840_BMSR )) ){		IF_DEQUEUE( &ifp->if_snd, m0 );		while( m0 ) {			m_freem(m0);			IF_DEQUEUE( &ifp->if_snd, m0 );		}		return;	}#endif	/* Link is OK, queue packets to NIC */	while( sc->pending_txs < TX_RING_SIZE  ){		buf = sc->tx_buffer + sc->cur_tx;		desc = sc->tx_desc + sc->cur_tx;		flist = sc->tx_flist + sc->cur_tx;		/* Get next packet to send */		IF_DEQUEUE( &ifp->if_snd, m0 );		/* If nothing to send, return */		if( NULL == m0 ) return;		/* If descriptor is busy, set IFF_OACTIVE and exit */		if( desc->status & 0x8000 ) {			dprintf((EPIC_FORMAT ": desc is busy in ifstart, up and down interface please\n",EPIC_ARGS(sc)));			break;		}		if( buf->mbuf ) {			dprintf((EPIC_FORMAT ": mbuf not freed in ifstart, up and down interface please\n",EPIC_ARGS(sc)));			break;		}		/* Fill fragments list */		for( m=m0, i=0;		    (NULL != m) && (i < EPIC_MAX_FRAGS);		    m = m->m_next, i++ ) {			flist->frag[i].fraglen = m->m_len; 			flist->frag[i].fragaddr = vtophys( mtod(m, caddr_t) );		}		flist->numfrags = i;		/* If packet was more than EPIC_MAX_FRAGS parts, */		/* recopy packet to new allocated mbuf cluster */		if( NULL != m ){			EPIC_MGETCLUSTER(m);			if( NULL == m ){				printf(EPIC_FORMAT ": cannot allocate mbuf cluster\n",EPIC_ARGS(sc));				m_freem(m0);				ifp->if_oerrors++;				continue;			}			m_copydata( m0, 0, m0->m_pkthdr.len, mtod(m,caddr_t) );			flist->frag[0].fraglen = 			     m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;			m->m_pkthdr.rcvif = ifp;			flist->numfrags = 1;			flist->frag[0].fragaddr = vtophys( mtod(m, caddr_t) );			m_freem(m0);			m0 = m;		}		buf->mbuf = m0;		sc->pending_txs++;		sc->cur_tx = ( sc->cur_tx + 1 ) & TX_RING_MASK;		desc->control = 0x01;		desc->txlength = 		    max(m0->m_pkthdr.len,ETHER_MIN_LEN-ETHER_CRC_LEN);		desc->status = 0x8000;		CSR_WRITE_4( sc, COMMAND, COMMAND_TXQUEUED );		/* Set watchdog timer */		ifp->if_timer = 8;#if NBPFILTER > 0		if( ifp->if_bpf ) #if defined(__FreeBSD__)			bpf_mtap( ifp, m0 );#else /* __OpenBSD__ */			bpf_mtap( ifp->if_bpf, m0 );#endif /* __FreeBSD__ */#endif	}	ifp->if_flags |= IFF_OACTIVE;	return;	}/* * * splimp() invoked before epic_intr_normal() */static __inline voidepic_rx_done __P((	epic_softc_t *sc )){	u_int16_t len;	struct epic_rx_buffer *buf;	struct epic_rx_desc *desc;	struct mbuf *m;	struct ether_header *eh;	while( !(sc->rx_desc[sc->cur_rx].status & 0x8000) ) { 		buf = sc->rx_buffer + sc->cur_rx;		desc = sc->rx_desc + sc->cur_rx;		/* Switch to next descriptor */		sc->cur_rx = (sc->cur_rx+1) & RX_RING_MASK;		/* Check for errors, this should happend */		/* only if SAVE_ERRORED_PACKETS is set, */		/* normaly rx errors generate RXE interrupt */		if( !(desc->status & 1) ) {			dprintf((EPIC_FORMAT ": Rx error status: 0x%x\n",EPIC_ARGS(sc),desc->status));			sc->sc_if.if_ierrors++;			desc->status = 0x8000;			continue;		}		/* Save packet length and mbuf contained packet */ 		len = desc->rxlength - ETHER_CRC_LEN;		m = buf->mbuf;		/* Try to get mbuf cluster */		EPIC_MGETCLUSTER( buf->mbuf );		if( NULL == buf->mbuf ) { 			printf(EPIC_FORMAT ": cannot allocate mbuf cluster\n",EPIC_ARGS(sc));			buf->mbuf = m;			desc->status = 0x8000;			sc->sc_if.if_ierrors++;			continue;		}		/* Point to new mbuf, and give descriptor to chip */		desc->bufaddr = vtophys( mtod( buf->mbuf, caddr_t ) );		desc->status = 0x8000;				/* First mbuf in packet holds the ethernet and packet headers */		eh = mtod( m, struct ether_header * );		m->m_pkthdr.rcvif = &(sc->sc_if);		m->m_pkthdr.len = m->m_len = len;#if NBPFILTER > 0		/* Give mbuf to BPFILTER */		if( sc->sc_if.if_bpf ) #if defined(__FreeBSD__)			bpf_mtap( &sc->sc_if, m );#else /* __OpenBSD__ */			bpf_mtap( sc->sc_if.if_bpf, m );#endif /* __FreeBSD__ */#endif /* NBPFILTER */#ifdef BRIDGE		if (do_bridge) {			struct ifnet *bdg_ifp ;			bdg_ifp = bridge_in(m);			if (bdg_ifp == BDG_DROP) {				if (m)					m_free(m);				continue; /* and drop */			}			if (bdg_ifp != BDG_LOCAL)				bdg_forward(&m, bdg_ifp);			if (bdg_ifp != BDG_LOCAL && bdg_ifp != BDG_BCAST &&				bdg_ifp != BDG_MCAST) {				if (m)					m_free(m);				continue; /* and drop */			}			/* all others accepted locally */		}#endif#if NBPFILTER > 0#ifdef BRIDGE		/*		 * This deserves explanation		 * If the bridge is _on_, then the following check		 * must not be done because occasionally the bridge		 * gets packets that are local but have the ethernet		 * address of one of the other interfaces.		 *		 * But if the bridge is off, then we have to drop		 * stuff that came in just via bpfilter.		 */		if (!do_bridge)#endif		/* Accept only our packets, broadcasts and multicasts */		if( (eh->ether_dhost[0] & 1) == 0 &&		    bcmp(eh->ether_dhost,sc->sc_macaddr,ETHER_ADDR_LEN)){			m_freem(m);			continue;		}#endif		/* Second mbuf holds packet ifself */		m->m_pkthdr.len = m->m_len = len - sizeof(struct ether_header);		m->m_data += sizeof( struct ether_header );		/* Give mbuf to OS */		ether_input(&sc->sc_if, eh, m);		/* Successfuly received frame */		sc->sc_if.if_ipackets++;        }	return;}/* * Synopsis: Do last phase of transmission. I.e. if desc is  * transmitted, decrease pending_txs counter, free mbuf contained * packet, switch to next descriptor and repeat until no packets * are pending or descriptor is not transmitted yet. */static __inline voidepic_tx_done __P((     register epic_softc_t *sc )){	struct epic_tx_buffer *buf;	struct epic_tx_desc *desc;	u_int16_t status;	while( sc->pending_txs > 0 ){		buf = sc->tx_buffer + sc->dirty_tx;		desc = sc->tx_desc + sc->dirty_tx;		status = desc->status;		/* If packet is not transmitted, thou followed */		/* packets are not transmitted too */		if( status & 0x8000 ) break;		/* Packet is transmitted. Switch to next and */		/* free mbuf */		sc->pending_txs--;		sc->dirty_tx = (sc->dirty_tx + 1) & TX_RING_MASK;		m_freem( buf->mbuf );		buf->mbuf = NULL;		/* Check for errors and collisions */		if( status & 0x0001 ) sc->sc_if.if_opackets++;

⌨️ 快捷键说明

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