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

📄 if_ix.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		if (ix_DoReq(mp, rp, IXC_GSTAT,	/* Get Stats */			 (caddr_t) ix->ix_ubaddr, sizeof(ix->ix_stats) - 8,			 rpb, 0))				return;		bcopy((caddr_t) &ix->ix_stats, (caddr_t) ix->ix_addr, 6);	}	ix->ix_if.if_flags |= IFF_RUNNING;	ix->ix_flags |= IXF_RUNNING;	ifp->if_watchdog = ixwatch;	ifp->if_timer = ix->ix_scaninterval = IXWATCHINTERVAL;	ixrint(mp, 0);}/* * Start output on interface. * Get another datagram to send off of the interface queue, * and map it to the interface before starting the output. */ixstart(ifp)struct ifnet *ifp;{        int len = 0;	int unit = ifp->if_unit;	register struct ix_softc *ix = &ix_softc[unit];	register struct mbuf *n;	struct mbuf *m;	int s, error = 0;	struct npmaster *mp = ix->ix_mp;	struct npreq *rp = ix->ix_wrp;	struct CQE *ep;	u_short rpb[8];	IF_DEQUEUE(&ix->ix_if.if_snd, m);	if (m == 0) {		if (ix->ix_flags & IXF_STATPENDING) {			ix->ix_flags &= ~IXF_STATPENDING;			ix->ix_if.if_flags |= IFF_OACTIVE;			rpb[0] = 2;			rpb[1] = ix->ix_aid;			rpb[2] = 0;			/* get all stats */			ix_DoReq(mp, rp, IXC_GSTAT,	/* general Stats */				 (caddr_t) ix->ix_ubaddr, sizeof(ix->ix_stats) - 8,				 rpb, ixcint);		}		return (0);	}	/*	 * Ensure minimum packet length.	 * This makes the safe assumtion that there are no virtual holes	 * after the data.	 * For security, it might be wise to zero out the added bytes,	 * but we're mainly interested in speed at the moment.	 */	len = if_wubaput(&ix->ix_ifuba, m);	if (len - sizeof(struct ether_header) < ETHERMIN)		len = ETHERMIN + sizeof(struct ether_header);	ix->ix_if.if_flags |= IFF_OACTIVE;	/* Now setup to call np driver */	rpb[0] = 8;	rpb[1] = ix->ix_aid;	ix_DoReq(mp, rp, IXC_XMIT,			 /* send frame */		    ix->ix_ifuba.ifu_w.ifrw_info, len, rpb, ixcint);	return (0);}/* * Command done interrupt. (almost) */ixcint(mp, rp)	struct npmaster *mp;	struct npreq *rp;{	struct CQE *ep;	register struct ix_softc *ix;	int s = splimp();	ep = rp->element;	ix = (struct ix_softc *)ep->cqe_famid;	ix->ix_flags &= ~IXF_OWATCH;	if ((ix->ix_if.if_flags & IFF_OACTIVE) == 0) {		printf("ix%d: stray xmit interrupt, npreq=%x\n",			ix->ix_if.if_unit, rp);	}	ix->ix_if.if_flags &= ~IFF_OACTIVE;	if (rp->flags & IOABORT || ep->cqe_sts != NPDONE	    || ep->cqe_ust0 != NPDONE || ep->cqe_ust1 != NPOK) {		if (ep->cqe_ust1 == 0x48)			ix->ix_if.if_oerrors++;		else {			struct ix_softc *ix = (struct ix_softc *)ep->cqe_famid;			printf(			   "ix%d: ixcint failed, cmd %x, stat %x, flags %x, ",				ix->ix_if.if_unit, rp->user,				ep->cqe_sts, rp->flags);			printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1);			if (++ix->ix_badcqe > 65) {				ix->ix_badcqe = 0;				printf("ixcint: shutting down unix dla\n");				ix->ix_if.if_flags &= ~IFF_UP;			}		 }	}	else switch (ep->cqe_func) {	case IXC_XMIT:		ix->ix_if.if_opackets++;		break;	case IXC_GSTAT:		ix->ix_if.if_collisions += ix->ix_stats.ixg.macg_xrty;	}done:	if (ix->ix_ifuba.ifu_xtofree) {		m_freem(ix->ix_ifuba.ifu_xtofree);		ix->ix_ifuba.ifu_xtofree = 0;	}	if ((ix->ix_if.if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING))		(void) ixstart(&ix->ix_if);	splx(s);}/* * Ethernet interface receiver interrupt. * If input error just drop packet. * Otherwise purge input buffered data path and examine  * packet to determine type.  If can't determine length * from type, then have to drop packet.  Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */ixrint(mp, rp)	struct npmaster *mp;	struct npreq *rp;{	struct CQE *ep;	register struct ix_softc *ix = ix_softc + mp->unit;	register struct ether_header *il;    	struct mbuf *m;	int len, off, resid, s;	register struct ifqueue *inq;	if ((ix->ix_flags & IXF_RUNNING) == 0)		return;	if (rp == 0)		goto setup;	ix->ix_flags &= ~(IXF_RCVPENDING|IXF_RWATCH);	ep = rp->element;	ix->ix_if.if_ipackets++;	if (ix->ix_ifuba.ifu_flags & UBA_NEEDBDP)		UBAPURGE(ix->ix_ifuba.ifu_uba, ix->ix_ifuba.ifu_r.ifrw_bdp);	il = (struct ether_header *)(ix->ix_ifuba.ifu_r.ifrw_addr);	len = ep->cqe_bcnt - sizeof (struct ether_header);	if (ep->cqe_sts != NPDONE || rp->flags & IOABORT	    || ep->cqe_ust0 != NPDONE	    || ep->cqe_ust1 != NPOK) {		printf("ix%drint: cqe error, cmd %x, stat %x, flags %x, ",			ix->ix_if.if_unit, rp->user, ep->cqe_sts, rp->flags);		printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1);		if (++ix->ix_badcqe > 50) {			ix->ix_badcqe = 0;			printf("ixrint: shutting down unix dla\n");			ix->ix_if.if_flags &= ~IFF_UP;			return;		}		goto setup;	}	if ( len < 46 || len > ETHERMTU) {		ix->ix_if.if_ierrors++;#ifdef notdef		if (ix->ix_if.if_ierrors % 100 == 0)			printf("ix%d: += 100 input errors\n", unit);#endif		goto setup;	}	/*	 * Deal with trailer protocol: if type is trailer type	 * get true type from first 16-bit word past data.	 * Remember that type was trailer by setting off.	 */	il->ether_type = ntohs((u_short)il->ether_type);#define	ildataaddr(il, off, type)	((type)(((caddr_t)((il)+1)+(off))))	if (il->ether_type >= ETHERTYPE_TRAIL &&	    il->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {		off = (il->ether_type - ETHERTYPE_TRAIL) * 512;		if (off >= ETHERMTU)			goto setup;		/* sanity */		il->ether_type = ntohs(*ildataaddr(il, off, u_short *));		resid = ntohs(*(ildataaddr(il, off+2, u_short *)));		if (off + resid > len)			goto setup;		/* sanity */		len = off + resid;	} else		off = 0;	if (len == 0)		goto setup;	/*	 * Pull packet off interface.  Off is nonzero if packet	 * has trailing header; ilget will then force this header	 * information to be at the front, but we still have to drop	 * the type and length which are at the front of any trailer data.	 */	m = if_rubaget(&ix->ix_ifuba, len, off, &ix->ix_if);	if (m)		ether_input(&ix->ix_if, il, m);setup:	/*	 * Reset for next packet if possible.	 * If waiting for transmit command completion, set flag	 * and wait until command completes.	 */	if (rp == 0) {		rp = ix->ix_rrp;		rp->intr = ixrint;		ep = rp->element;	}	len = ETHERMTU + sizeof(struct ether_header);	/* Now setup to call np driver */	/* Initializations of request structure */	ep->cqe_func = IXC_RECV;			/* get frame */	ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR;		/* Clear status */	ep->cqe_bcnt = len;				/* Byte count */	ep->cqe_lenrpb = 10;				/* RPB length */	ep->rpb1 = ix->ix_aid;				/* which channel */	ep->rpb2 = 65535;				/* Timeout */	ix->ix_flags |= IXF_RCVPENDING;	s = spl5();	NpAddCQE(ep, &mp->shmemp->devcq, mp); /* Add CQE to device's queue */	splx(s);}long ixwatchcount;/* * Watchdog routine, request statistics from board. */ixwatch(unit)	int unit;{	register struct ix_softc *ix = &ix_softc[unit];	register struct ifnet *ifp = &ix->ix_if;	int s;	ixwatchcount++;	if (ix->ix_badcqe > 1) {		ix->ix_badcqe--; /* If errors aren't happening too fast,				give the board a reprieve */	}	s = splimp();	if (ix->ix_flags & IXF_STATPENDING) {		ifp->if_timer = ix->ix_scaninterval;		ix->ix_flags |= IXF_OWATCH;		splx(s);		return;	}	ix->ix_flags |= IXF_STATPENDING;	if ((ix->ix_if.if_flags & IFF_OACTIVE) == 0)		(void) ixstart(ifp);	else		ix->ix_flags |= IXF_OWATCH;	if (ix->ix_flags & IXF_RCVPENDING)		ix->ix_flags |= IXF_RWATCH;	splx(s);	ifp->if_timer = ix->ix_scaninterval;}/* * Process an ioctl request. */ixioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	register struct ifaddr *ifa = (struct ifaddr *)data;	register struct ix_softc *ix = &ix_softc[ifp->if_unit];	int s = splimp(), error = 0;	switch (cmd) {	case SIOCSIFADDR:		ifp->if_flags |= IFF_UP;		ixinit(ifp->if_unit);		if ((ifp->if_flags & IFF_UP) == 0)			return (EBUSY);		switch (ifa->ifa_addr->sa_family) {#ifdef INET		case AF_INET:			((struct arpcom *)ifp)->ac_ipaddr =				IA_SIN(ifa)->sin_addr;			arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);			break;#endif#ifdef NS		case AF_NS:		    {			register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);						if (ns_nullhost(*ina)) {				ina->x_host = * (union ns_host *) 				     (ix_softc[ifp->if_unit].ix_addr);			} else {			    return				ix_setaddr(ina->x_host.c_host, ifp->if_unit);			}			break;		    }#endif		}		break;	case SIOCSIFFLAGS:		if ((ifp->if_flags & IFF_UP) == 0 &&		    ix->ix_flags & IXF_RUNNING) {			ix->ix_flags &= ~IXF_RUNNING;			NpReset(ix->ix_mp, 0);		} else if (ifp->if_flags & IFF_UP &&		    (ix->ix_flags & IXF_RUNNING) == 0)			ixinit(ifp->if_unit);		break;	default:		error = EINVAL;	}	splx(s);	return (error);}/* * set ethernet address for unit */ix_setaddr(physaddr, unit)u_char *physaddr;int unit;{	register struct ix_softc *ix = &ix_softc[unit];		if (! (ix->ix_flags & IXF_RUNNING))		return (EBUSY);	/* The following is a big cop out due to the fact that	   Changing the ethernet address resets the dla module,	   so must re-open the channel, anyway. */	bcopy((caddr_t)physaddr, (caddr_t)ix->ix_addr, sizeof ix->ix_addr);	ix->ix_flags &= ~IXF_RUNNING;	ix->ix_flags |= IXF_SETADDR;	ixinit(unit);	NpKill(ix->ix_mp, ix->ix_rrp);}static showme() {	return ((int) &(ix_softc->ix_badcqe));}#endif

⌨️ 快捷键说明

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