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

📄 if_xna.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * the port. Wakeup anyone waiting for command completions.	 */	for (index = ((sc->tlast+1)%nNXNACMD), tp = &sc->tring[index];	     (sc->nxmit > 0 && (tp->status & ST_TOWN));	     index = ++index % nNXNACMD, tp = &sc->tring[index]) {		/*		 * Process cmd/xmit descriptor		 */		mp = tp->mbuf_tofree;		tp->mbuf_tofree = 0;		if (tp->status & ST_CMD) {		/* Command */			struct xnacmd_buf *xcmd;			/*			 * Grab command buffer address from mbuf wrapper.			 * Process which posted command will free both the			 * wrapper and the command buffer.			 */			xcmd = mtod(mp, struct xnacmd_buf *);			switch (xcmd->opcode) {				case CMD_RCCNTR:					if (!(tp->status & ST_TERR)) {						bzero(&sc->ctrblk,					           sizeof(struct xnacmd_buf));						sc->ztime = time.tv_sec;					}				case CMD_RDCNTR:					/*					 * Make certain we don't attempt to					 * free the ctrblk region of the softc					 */					mp->m_off = MMINOFF;					mp->m_len = MLEN;					m_freem(mp);					break;				case CMD_NOP:					/*					 * XNATIMEOUT timer went off before this					 * command was processed; simply free					 * the mbuf, since the person who					 * issued this command has gone away.					 */					printf ("xna%d: command timed out\n");					m_freem(mp);					break;				case CMD_PARAM:				case CMD_SYSID:				case CMD_USTART:				case CMD_UCHANGE:				case CMD_USTOP:					/*		 			 * On command failure, alert caller					 * by invalidating the command opcode.					 */					if (tp->status & ST_TERR) {						printf ("xna%d: command failed, error code: 0x%x\n", unit, tp->error);						xcmd->opcode = CMD_INVAL;					} else						xcmd->opcode = CMD_COMPLETE;					break;				default:					xcmd->opcode = CMD_INVAL;					break;			}		} else {				/* Transmit */			if (tp->status & ST_TERR) {				sc->is_if.if_oerrors++;				m_freem(mp);			} else {				sc->is_if.if_opackets++;				/*				 * Loop back any broadcasts we send				 */				if ((!(bcmp(mtod(mp, caddr_t),					    etherbroadcastaddr, 6))) || (sc->is_if.if_flags & IFF_PFCOPYALL)) {					struct mbuf *m0 = mp;					int len = 0;					while (m0) {						len += m0->m_len;						m0 = m0->m_next;					}					xnaread(sc, 0, len, mp);				} else {					m_freem(mp);				}			}		}		sc->tlast = index;	/* Last cmd/xmit processed */		sc->nxmit--;		sc->nproc++;	}	}	/*	 * Dequeue next transmit request if interface is no longer busy.	 */	if (sc->nxmit <= 0) {		sc->is_if.if_flags &= ~IFF_OACTIVE;		xnastart( unit );	}	/*	 * Ring Release function. Tell port how many ring entries we've	 * processed. Drop softc lock and return from interrupt.	 */	addr->xnapd2 = sc->nproc;	smp_unlock(&sc->lk_xna_softc);	splx(s);}/* * XNA read routine. Pass input packets up to higher levels. */xnaread (sc, m, len, swloop)	register struct xna_softc *sc;	struct mbuf *m;	register int len;	struct mbuf *swloop;{	register struct ether_header *eptr;	register int off, resid;	struct mbuf *swloop_tmp1;	struct ether_header eh;	struct protosw *pr;	struct ifqueue *inq;	/*	 * Deal with trailer protocol: if type is INET trailer	 * get true type from first 16-bit word past data.	 * Remember that type was trailer by setting off.	 */	if (swloop) {#ifdef	mips		/*		 * Architectures which place the adapter in physical		 * addressing mode must data copy mbuf chains into a		 * cluster. (Which is known to be physically contig.)		 * This cluster will be tagged to the end of the actual		 * chain and must be freed before we continue.		 */		for (swloop_tmp1 = swloop; swloop_tmp1->m_next->m_next;		     swloop_tmp1 = swloop_tmp1->m_next);		m_freem(swloop_tmp1->m_next);		swloop_tmp1->m_next = 0;#endif	mips		eptr = mtod(swloop, struct ether_header *);		eh = *eptr;		eptr = &eh;		if ( swloop->m_len > sizeof(struct ether_header))			m_adj(swloop, sizeof(struct ether_header));		else {			MFREE(swloop, swloop_tmp1);			if ( ! swloop_tmp1 )				return;			else				swloop = swloop_tmp1;		}	} else {		m->m_len = len -= 4;	/* subtract 4 bytes CRC */		eptr = mtod(m, struct ether_header *);		eh = *eptr;		eptr = &eh;	}	eptr->ether_type = ntohs((u_short)eptr->ether_type);	if ((eptr->ether_type >= ETHERTYPE_TRAIL &&	    eptr->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER)) {		off = (eptr->ether_type - ETHERTYPE_TRAIL) * 512 +		      sizeof(struct ether_header);		if (off >= ETHERMTU)			return;		/* sanity */		if (swloop) {			struct mbuf *mprev, *m0 = swloop;/* need to check this against off */			mprev = m0;			while (swloop->m_next){/*real header at end of chain*/				mprev = swloop;				swloop = swloop->m_next;			}			/* move to beginning of chain */			mprev->m_next = 0;			swloop->m_next = m0;			eptr->ether_type = ntohs( *mtod(swloop, u_short *));		} else {		        eptr->ether_type =				ntohs(*(short *)(mtod(m, caddr_t) + off));			resid = ntohs(*(short *)(mtod(m, caddr_t) + off +2));			if (off + resid > m->m_len)			     return;		/* sanity */		}	} else {		off = 0;	}	/*	 * Pull packet off interface. (In the case of the XNA, only need	 * to shuffle trailer data around, then hand up the address of the	 * mbuf we had tied to the receive descriptor.) Off is nonzero if	 * packet has trailing header; need to 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.	 */	if (swloop) {		m = m_copy(swloop, 0, M_COPYALL);		m_freem(swloop);		if (m == 0)			return;	} else {		struct mbuf *m0 = m;		if (off) {			int nbytes;			int cnt = resid;			struct mbuf *n;			struct mbuf **mp = &m;			while (cnt > 0) {				MGET(n, M_DONTWAIT, MT_DATA);				if (n == 0) {					m_freem(m);					return;				}				nbytes = MIN(MLEN, cnt);				bcopy((mtod(m, caddr_t) + off),				       mtod(n, caddr_t), nbytes);				n->m_len = nbytes;				off += nbytes;				cnt -= nbytes;				*mp = n;				mp = &n->m_next;			}			/*			 * Done hoisting trailer data; tie m0 onto the			 * end of the chain, and drop trailer data length			 */			*mp = m0;			m0->m_len -= resid;			/*			 * Adjust head of chain for trailer header			 */			m->m_off += 2 * sizeof (u_short);			m->m_len -= 2 * sizeof (u_short);		}		/*		 * Trim off ethernet header		 */		m0->m_off += sizeof (struct ether_header);		m0->m_len -= sizeof (struct ether_header);	}	/*	 * Subtract length of header from len	 */	len -= sizeof (struct ether_header);	/* Dispatch this packet */	net_read(&(sc->is_ed), eptr, m, len, (swloop != NULL), (off != 0));}/* * Process an ioctl request. */xnaioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	register struct xna_softc *sc = &xna_softc[ifp->if_unit];	register struct xnadevice *addr = &sc->xregs;	register struct xnacmd_buf *xcmd;	struct protosw *pr;	struct mbuf *m;	struct ifreq *ifr = (struct ifreq *)data;	struct ifdevea *ifd = (struct ifdevea *)data;	register struct ifaddr *ifa = (struct ifaddr *)data;	struct ctrreq *ctr = (struct ctrreq *)data;	int s, error = 0;	switch (cmd) {        case SIOCENABLBACK:        case SIOCDISABLBACK:		if (cmd == SIOCENABLBACK)                	ifp->if_flags |= IFF_LOOPBACK;		else                	ifp->if_flags &= ~IFF_LOOPBACK;		if (ifp->if_flags & IFF_RUNNING) {			/*			 * Lock softc. Same comments as for "xnainit()"			 */			s = splimp();			smp_lock(&sc->lk_xna_softc, LK_RETRY);			if (m = xnamkparam(sc, ifp)) {				xnacmd(sc, m);				smp_unlock(&sc->lk_xna_softc);				splx(s);				xcmd = mtod(m, struct xnacmd_buf *);				XNATIMEOUT(xcmd, CMD_PARAM); /* Wait */				switch (xcmd->opcode) {					case CMD_COMPLETE:						m_freem(m);						break;					case CMD_INVAL:						m_freem(m);					case CMD_NOP:					default:						error = EINVAL;						break;				}			} else {				smp_unlock(&sc->lk_xna_softc);				error = ENOBUFS;				splx(s);			}		}                break;         case SIOCRPHYSADDR:                 /*                 * read default hardware address. Lock softc while accessing		 * per-unit physical address info.                 */		s = splimp();		smp_lock(&sc->lk_xna_softc, LK_RETRY);		bcopy(sc->is_dpaddr, ifd->default_pa, 6);		bcopy(sc->is_addr, ifd->current_pa, 6);		smp_unlock(&sc->lk_xna_softc);		splx(s);                break; 	case SIOCSPHYSADDR: 		/* 		 * Set physaddr. Lock softc while updating per-unit physical		 * address, and for command processing as in "xnainit()".		 */		s = splimp();		smp_lock(&sc->lk_xna_softc, LK_RETRY);		bcopy(ifr->ifr_addr.sa_data, sc->is_addr, 6);#if	NPACKETFILTER > 0		pfilt_newaddress(sc->is_ed.ess_enetunit, sc->is_addr);#endif	NPACKETFILTER		if (ifp->if_flags & IFF_RUNNING) {			if (m = xnamkparam(sc, ifp)) {				xnacmd(sc, m);				smp_unlock(&sc->lk_xna_softc);				splx(s);				xcmd = mtod(m, struct xnacmd_buf *);				XNATIMEOUT(xcmd, CMD_PARAM); /* Wait */				switch (xcmd->opcode) {					case CMD_COMPLETE:						m_freem(m);						break;					case CMD_INVAL:						m_freem(m);					case CMD_NOP:					default:						error = EINVAL;						break;				}			} else {				smp_unlock(&sc->lk_xna_softc);				error = ENOBUFS;				splx(s);			}		} else {			smp_unlock(&sc->lk_xna_softc);			splx(s);                	xnainit(ifp->if_unit);		}		break;	case SIOCDELMULTI: 	case SIOCADDMULTI: 		/*		 * Lock softc while updating per-unit multicast address		 * list and for command processing as in "xnainit()".		 */		s = splimp();		smp_lock(&sc->lk_xna_softc, LK_RETRY);		if (cmd == SIOCDELMULTI) {			/*			 * If we're deleting a multicast address, decrement			 * the is_muse count and invalidate the address if			 * count goes to zero.			 */			int i;			for (i = 0; i < NMULTI; i++) {				if (bcmp(sc->is_multi[i],				    ifr->ifr_addr.sa_data,6) == 0)					break;			}			if ((i < NMULTI) && (--sc->is_muse[i] == 0))				bcopy(etherbroadcastaddr,sc->is_multi[i],6);			else {				smp_unlock(&sc->lk_xna_softc);				splx(s);				goto done;			}		} else {			/*			 * If we're adding a multicat address, increment the			 * is_muse count if it's already in our table, and			 * return. Otherwise, add it to the table or return			 * ENOBUFS if we're out of entries.			 */			int i, j = -1;			for (i = 0; i < NMULTI; i++) {				if (bcmp(sc->is_multi[i],				    ifr->ifr_addr.sa_data,6) == 0) {					sc->is_muse[i]++;					smp_unlock(&sc->lk_xna_softc);					splx(s);					goto done;				}				if ((j < 0) && (bcmp(sc->is_multi[i],				    etherbroadcastaddr,6) == 0))					j = i;			}			if (j < 0) {				printf("xna%d: addmulti failed, multicast list full: %d\n",					ifp->if_unit, NMULTI);				smp_unlock(&sc->lk_xna_softc);				error = ENOBUFS;				splx(s);				goto done;			} else {		    		bcopy(ifr->ifr_addr.sa_data,				      sc->is_multi[j], 6);		    		sc->is_muse[j]++;			}		}		if (ifp->if_flags & IFF_RUNNING) {			/*			 * If we've successfully init'ed the interface,			 * issue a UCHANGE command to update the ethernet			 * user's multicast address list. Otherwise, the			 * list will be initialized upon the first call			 * to "xnainit()".			 */			if (m = xnamkuser(sc, XNA_ETHERU, CMD_UCHANGE)) {				xnacmd(sc, m);				smp_unlock(&sc->lk_xna_softc);				splx(s);				xcmd = mtod(m, struct xnacmd_buf *);				XNATIMEOUT(xcmd, CMD_UCHANGE);	/* Wait */				switch (xcmd->opcode) {					case CMD_COMPLETE:						m_freem(m);						break;					case CMD_INVAL:						m_freem(m);					case CMD_NOP:					default:						error = EINVAL;

⌨️ 快捷键说明

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