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

📄 if_ec.c

📁 open bsd vax module -if function
💻 C
📖 第 1 页 / 共 2 页
字号:
		/*		 * Reset interface, then requeue rcv buffers.		 * Some incoming packets may be lost, but that		 * can't be helped.		 */		addr->ec_xcr = EC_UECLR;#ifdef MULTI		if (es->es_if.if_flags & IFF_PROMISC)			start_read = EC_PROMISC;		else if (es->es_if.if_flags & IFF_MULTI)			start_read = EC_MULTI;		else#endif MULTI			start_read = EC_READ;		for (i=ECRHBF; i>=ECRLBF; i--)			addr->ec_rcr = start_read|i;		/*		 * Reset and transmit next packet (if any).		 */		es->es_if.if_flags &= ~IFF_OACTIVE;		es->es_mask = ~0;		if (es->es_if.if_snd.ifq_head)			(void) ecstart(&es->es_if);		return;	}	/*	 * Do exponential backoff.  Compute delay based on low bits	 * of the interval timer (1 bit for each transmission attempt,	 * but at most 5 bits).  Then delay for that number of	 * slot times.  A slot time is 51.2 microseconds (rounded to 51).	 * This does not take into account the time already used to	 * process the interrupt.	 */	es->es_mask <<= 1;	delay = mfpr(ICR) & 0x1f &~ es->es_mask;	DELAY(delay * 51);	/*	 * Clear the controller's collision flag, thus enabling retransmit.	 */	addr->ec_xcr = EC_CLEAR;}/* * Ethernet interface receiver interrupt. * If input error just drop packet. * Otherwise 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. */ecrint(unit)	int unit;{	struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;	while (addr->ec_rcr & EC_RDONE)		ecread(unit);}ecread(unit)	int unit;{	register struct ec_softc *es = &ec_softc[unit];	struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;	register struct ether_header *ec;    	struct mbuf *m;	int len, off, resid, ecoff, rbuf;	register struct ifqueue *inq;	u_short start_read;	u_char *ecbuf;	es->es_if.if_ipackets++;	rbuf = addr->ec_rcr & EC_RBN;	if (rbuf < ECRLBF || rbuf > ECRHBF)		panic("ecrint");	ecbuf = es->es_buf[rbuf];	ecoff = *(short *)ecbuf;	if (ecoff <= ECRDOFF || ecoff > 2046) {		es->es_if.if_ierrors++;#ifdef notdef		if (es->es_if.if_ierrors % 100 == 0)			printf("ec%d: += 100 input errors\n", unit);#endif		goto setup;	}	/*	 * Get input data length.	 * Get pointer to ethernet header (in input buffer).	 * 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.	 */	len = ecoff - ECRDOFF - sizeof (struct ether_header);	ec = (struct ether_header *)(ecbuf + ECRDOFF);	ec->ether_type = ntohs((u_short)ec->ether_type);#define	ecdataaddr(ec, off, type)	((type)(((caddr_t)((ec)+1)+(off))))	if (ec->ether_type >= ETHERTYPE_TRAIL &&	    ec->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {		off = (ec->ether_type - ETHERTYPE_TRAIL) * 512;		if (off >= ETHERMTU)			goto setup;		/* sanity */		ec->ether_type = ntohs(*ecdataaddr(ec, off, u_short *));		resid = ntohs(*(ecdataaddr(ec, 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; ecget 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 = ecget(ecbuf, len, off, &es->es_if);	if (m)		ether_input(&es->es_if, ec, m);	/*	 * Reset for next packet.	 */setup:#ifdef MULTI		if (es->es_if.if_flags & IFF_PROMISC)			start_read = EC_PROMISC;		else if (es->es_if.if_flags & IFF_MULTI)			start_read = EC_MULTI;		else#endif MULTI			start_read = EC_READ;	addr->ec_rcr = start_read|EC_RCLR|rbuf;}/* * Routine to copy from mbuf chain to transmit * buffer in UNIBUS memory. * If packet size is less than the minimum legal size, * the buffer is expanded.  We probably should zero out the extra * bytes for security, but that would slow things down. */ecput(ecbuf, m)	u_char *ecbuf;	struct mbuf *m;{	register struct mbuf *mp;	register int off;	u_char *bp;	for (off = 2048, mp = m; mp; mp = mp->m_next)		off -= mp->m_len;	if (2048 - off < ETHERMIN + sizeof (struct ether_header))		off = 2048 - ETHERMIN - sizeof (struct ether_header);	*(u_short *)ecbuf = off;	bp = (u_char *)(ecbuf + off);	for (mp = m; mp; mp = mp->m_next) {		register unsigned len = mp->m_len;		u_char *mcp;		if (len == 0)			continue;		mcp = mtod(mp, u_char *);		if ((unsigned)bp & 01) {			*bp++ = *mcp++;			len--;		}		if (off = (len >> 1)) {			register u_short *to, *from;			to = (u_short *)bp;			from = (u_short *)mcp;			do				*to++ = *from++;			while (--off > 0);			bp = (u_char *)to,			mcp = (u_char *)from;		}		if (len & 01)			*bp++ = *mcp++;	}	m_freem(m);}/* * Routine to copy from UNIBUS memory into mbufs. * Similar in spirit to if_rubaget. * * Warning: This makes the fairly safe assumption that * mbufs have even lengths. */struct mbuf *ecget(ecbuf, totlen, off0, ifp)	u_char *ecbuf;	int totlen, off0;	struct ifnet *ifp;{	register struct mbuf *m;	struct mbuf *top = 0, **mp = &top;	register int off = off0, len;	u_char *cp = (ecbuf += ECRDOFF + sizeof (struct ether_header));	u_char *packet_end = cp + totlen;	if (off) {		off += 2 * sizeof(u_short);		totlen -= 2 *sizeof(u_short);		cp += off;	}	MGETHDR(m, M_DONTWAIT, MT_DATA);	if (m == 0)		return (0);	m->m_pkthdr.rcvif = ifp;	m->m_pkthdr.len = totlen;	m->m_len = MHLEN;	while (totlen > 0) {		register int words;		u_char *mcp;		if (top) {			MGET(m, M_DONTWAIT, MT_DATA);			if (m == 0) {				m_freem(top);				return (0);			}			m->m_len = MLEN;		}		len = min(totlen, (packet_end - cp));		if (len >= MINCLSIZE) {			MCLGET(m, M_DONTWAIT);			if (m->m_flags & M_EXT)				m->m_len = len = min(len, MCLBYTES);			else				len = m->m_len;		} else {			/*			 * Place initial small packet/header at end of mbuf.			 */			if (len < m->m_len) {				if (top == 0 && len + max_linkhdr <= m->m_len)					m->m_data += max_linkhdr;				m->m_len = len;			} else				len = m->m_len;		}		mcp = mtod(m, u_char *);		if (words = (len >> 1)) {			register u_short *to, *from;			to = (u_short *)mcp;			from = (u_short *)cp;			do				*to++ = *from++;			while (--words > 0);			mcp = (u_char *)to;			cp = (u_char *)from;		}		if (len & 01)			*mcp++ = *cp++;		*mp = m;		mp = &m->m_next;		totlen -= len;		if (cp == packet_end)			cp = ecbuf;	}	return (top);bad:	m_freem(top);	return (0);}/* * Process an ioctl request. */ecioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	register struct ifaddr *ifa = (struct ifaddr *)data;	struct ec_softc *es = &ec_softc[ifp->if_unit];	struct ecdevice *addr;	int s = splimp(), error = 0;	addr = (struct ecdevice *)(ecinfo[ifp->if_unit]->ui_addr);	switch (cmd) {	case SIOCSIFADDR:		ifp->if_flags |= IFF_UP;		switch (ifa->ifa_addr->sa_family) {#ifdef INET		case AF_INET:			ecinit(ifp->if_unit);	/* before arpwhohas */			((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 *)(es->es_addr);			else {				/* 				 * The manual says we can't change the address 				 * while the receiver is armed,				 * so reset everything				 */				ifp->if_flags &= ~IFF_RUNNING; 				bcopy((caddr_t)ina->x_host.c_host,				    (caddr_t)es->es_addr, sizeof(es->es_addr));			}			ecinit(ifp->if_unit); /* does ec_setaddr() */			break;		    }#endif		default:			ecinit(ifp->if_unit);			break;		}		break;	case SIOCSIFFLAGS:		if ((ifp->if_flags & IFF_UP) == 0 &&		    ifp->if_flags & IFF_RUNNING) {			addr->ec_xcr = EC_UECLR;			ifp->if_flags &= ~IFF_RUNNING;		} else if (ifp->if_flags & IFF_UP &&		    (ifp->if_flags & IFF_RUNNING) == 0)			ecinit(ifp->if_unit);		break;	default:		error = EINVAL;	}	splx(s);	return (error);}ec_setaddr(physaddr,unit)	u_char *physaddr;	int unit;{	struct ec_softc *es = &ec_softc[unit];	struct uba_device *ui = ecinfo[unit];	register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;	register char nibble;	register int i, j;	/*	 * Use the ethernet address supplied	 * Note that we do a UECLR here, so the receive buffers	 * must be requeued.	 */	#ifdef DEBUG	printf("ec_setaddr: setting address for unit %d = %s",		unit, ether_sprintf(physaddr));#endif	addr->ec_xcr = EC_UECLR;	addr->ec_rcr = 0;	/* load requested address */	for (i = 0; i < 6; i++) { /* 6 bytes of address */	    es->es_addr[i] = physaddr[i];	    nibble = physaddr[i] & 0xf; /* lower nibble */	    addr->ec_rcr = (nibble << 8);	    addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */	    addr->ec_rcr = (nibble << 8);	    for (j=0; j < 4; j++) {		addr->ec_rcr = 0;		addr->ec_rcr = EC_ASTEP; /* step counter */		addr->ec_rcr = 0;	    }	    nibble = (physaddr[i] >> 4) & 0xf; /* upper nibble */	    addr->ec_rcr = (nibble << 8);	    addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */	    addr->ec_rcr = (nibble << 8);	    for (j=0; j < 4; j++) {		addr->ec_rcr = 0;		addr->ec_rcr = EC_ASTEP; /* step counter */		addr->ec_rcr = 0;	    }	}#ifdef DEBUG	/*	 * Read the ethernet address off the board, one nibble at a time.	 */	addr->ec_xcr = EC_UECLR;	addr->ec_rcr = 0; /* read RAM */	cp = es->es_addr;#undef NEXTBIT#define	NEXTBIT	addr->ec_rcr = EC_ASTEP; addr->ec_rcr = 0	for (i=0; i < sizeof (es->es_addr); i++) {		*cp = 0;		for (j=0; j<=4; j+=4) {			*cp |= ((addr->ec_rcr >> 8) & 0xf) << j;			NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;		}		cp++;	}	printf("ec_setaddr: RAM address for unit %d = %s",		unit, ether_sprintf(physaddr));#endif}#endif

⌨️ 快捷键说明

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