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

📄 if_dmc.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
			break;		report:			printd("dmc%d: soft error, flags=%b\n", unit,			    arg, CNTLO_BITS);			if ((sc->sc_flag & DMC_RESTART) == 0) {				/*				 * kill off the dmc to get things				 * going again by generating a				 * procedure error				 */				sc->sc_flag |= DMC_RESTART;				arg = sc->sc_ubinfo & 0x3ffff;				dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM);			}			break;		default:			printf("dmc%d: bad control %o\n", unit, cmd);			break;		}	}	dmcstart(unit);        return;}/* * DMC state routine * This routine either halts the DMC or sets it up to operate * in a particular mode. */dmcstate(ifp, sc, ui)        register struct ifnet *ifp;        register struct dmc_softc *sc;        register struct uba_device *ui;{	ifp->if_addr.sa_family = sc->sc_dmccs.if_family; 	if ( sc->sc_dmccs.if_ustate == IFS_USROFF ) {		sc->sc_dmccs.if_mode = ui->ui_flags;		sc->sc_dmccs.if_dstate = IFS_HALTED;	} else {		    sc->sc_dmccs.if_dstate = IFS_STARTING;	}}/* * DMC output routine. * Encapsulate a packet of type family for the dmc. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. */dmcoutput(ifp, m0, dst)        register struct ifnet *ifp;        register struct mbuf *m0;        struct sockaddr *dst;{	register struct dmc_softc *sc = &dmc_softc[ifp->if_unit];        int type, error, s;        register struct mbuf *m = m0;	register struct dmc_header *dh;	register int off;	struct protosw *pr;        struct ifqueue *inq;	/*	 * check for device ownership if if_nomuxhdr is asserted!	 */	if ( (sc->sc_dmccs.if_nomuxhdr) && (ifp->if_addr.sa_family != dst->sa_family) )	{		error = EADDRINUSE;		goto bad;	}	switch (dst->sa_family) {#ifdef	INET	case AF_INET:		off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;		if ((ifp->if_flags & IFF_NOTRAILERS) == 0)		if (off > 0 && (off & 0x1ff) == 0 &&		    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {			type = DMC_TRAILER + (off>>9);			m->m_off -= 2 * sizeof (u_short);			m->m_len += 2 * sizeof (u_short);			*mtod(m, u_short *) = htons((u_short)DMC_IPTYPE);			*(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);			goto gottrailertype;		}		type = DMC_IPTYPE;		off = 0;		goto gottype;#endif	case AF_UNSPEC:		dh = (struct dmc_header *)dst->sa_data;		type = dh->dmc_type;		goto gottype;	default:		if ((pr=iffamily_to_proto(ifp->if_addr.sa_family)) && pr->pr_ifoutput) 			(*pr->pr_ifoutput)(ifp, m, dst, &type, NULL);		else {			printf("dmc%d: can't handle af%d\n", ifp->if_unit,				dst->sa_family);			error = EAFNOSUPPORT;			goto bad;		}		goto gottype;        }gottrailertype:	/*	 * Packet to be sent as a trailer; move first packet	 * (control information) to end of chain.	 */	while (m->m_next)		m = m->m_next;	m->m_next = m0;	m = m0->m_next;	m0->m_next = 0;	m0 = m;gottype:	/*	 * Add local header only if if_nomuxhdr is NOT asserted!	 * (there is space for a uba on a vax to step on)	 */	if ( ! sc->sc_dmccs.if_nomuxhdr ) {		if (m->m_off > MMAXOFF ||		    MMINOFF + sizeof(struct dmc_header) > m->m_off) {			m = m_get(M_DONTWAIT, MT_DATA);			if (m == 0) {				error = ENOBUFS;				goto bad;			}			m->m_next = m0;			m->m_off = MMINOFF;			m->m_len = sizeof (struct dmc_header);		} else {			m->m_off -= sizeof (struct dmc_header);			m->m_len += sizeof (struct dmc_header);		}		dh = mtod(m, struct dmc_header *);		dh->dmc_type = htons((u_short)type);	}	/*	 * Queue message on interface, and start output if interface	 * not yet active.	 */	s = splimp();        if (IF_QFULL(&ifp->if_snd)) {                IF_DROP(&ifp->if_snd);                m_freem(m);                splx(s);                return (ENOBUFS);        }        IF_ENQUEUE(&ifp->if_snd, m);        dmcstart(ifp->if_unit);        splx(s);        return(0);bad:	m_freem(m0);	return(error);}/* * Process an ioctl request. */dmcioctl(ifp, cmd, data)        register struct ifnet *ifp;        int cmd;        caddr_t data;{        int s = splimp(), error = 0;	int arg;	register struct dmc_softc *sc = &dmc_softc[ifp->if_unit];	register struct uba_device *ui = dmcinfo[ifp->if_unit];        switch (cmd) {	case SIOCSTATE:		/*		 * read and/or set current ownership and state of device.		 */		{			register struct ifstate *dmcstate = (struct ifstate *) data;			register struct protosw *pr;			register struct ifaddr *ifa;			for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)				if (ifa->ifa_addr.sa_family && ifa->ifa_dstaddr.sa_family)					break;			if (ifa == (struct ifaddr *) 0)				return(ENETDOWN);			if ( ! dmcsuser() ) 				return(EACCES);			/*			 * If currently owned by another family, request			 * ownership from that family.			 */			if (ifp->if_addr.sa_family && (ifp->if_addr.sa_family != dmcstate->if_family)) {				if ((pr=iffamily_to_proto(ifp->if_addr.sa_family)) && pr->pr_ifstate) 				{					if (! (*pr->pr_ifstate)(ifp, IFS_OWNREQ, dmcstate)) 						return(EBUSY);					else						dmcstate->if_next_family = ifp->if_addr.sa_family;				}				else					return(EBUSY);			}			/*			 * check validity of ioctl request			 */			if ( !( dmcstate->if_wrstate | dmcstate->if_rdstate | dmcstate->if_xferctl ) )				return(EINVAL);			/*			 * set line ownership			 */			if ( dmcstate->if_wrstate ) {				ifp->if_addr.sa_family = dmcstate->if_family;				bcopy(dmcstate, &sc->sc_dmccs, sizeof(struct ifstate));				sc->sc_dmccs.if_wrstate = ~IFS_WRSTATE;				sc->sc_dmccs.if_rdstate = ~IFS_RDSTATE;				sc->sc_dmccs.if_xferctl = ~IFS_XFERCTL;			}			/*			 * current owner can transfer control to another family			 */			if ( dmcstate->if_xferctl && dmcstate->if_wrstate ) {				ifp->if_addr.sa_family = (sc->sc_dmccs.if_family = sc->sc_dmccs.if_next_family);				sc->sc_dmccs.if_next_family = ifp->if_addr.sa_family;			}			if ( dmcstate->if_wrstate ) {				/*				 * If stopping line, force procedure error in				 *	order to drop dtr and restart device.				 * Else if currently running, just restart device.				 * Otherwise start protocol.				 */				if ( dmcstate->if_ustate == IFS_USROFF &&					(sc->sc_flag & (DMC_ALLOC | DMC_BMAPPED)) == (DMC_ALLOC | DMC_BMAPPED) &&					(sc->sc_flag & DMC_RESTART) == 0 ) {					sc->sc_flag |= DMC_RESTART;					ifp->if_flags &= ~IFF_UP;					sc->sc_dmccs.if_dstate = IFS_HALTING;					arg = sc->sc_ubinfo & 0x3ffff;					dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM);				} else {					if ( (sc->sc_flag & DMC_RESTART) == 0 ) {						sc->sc_flag |= DMC_RESTART;						ifp->if_flags &= ~IFF_UP;						sc->sc_dmccs.if_dstate = IFS_HALTING;						dmcrestart(ifp->if_unit);					}				}			}			/*			 * pass back current state if requested.			 */			if ( dmcstate->if_rdstate ) {				bcopy(&sc->sc_dmccs, dmcstate, sizeof(struct ifstate));			}		break;		}	case SIOCENABLBACK:	/*	 * place device in loopback	 */		if ( ! dmcsuser() ) 			return(EACCES);		printf("dmc%d: internal loopback enable requested\n", ifp->if_unit);		ifp->if_flags |= IFF_LOOPBACK;		/*		 * kill off the dmc to reset state		 * by generating a procedure error		 */		if ((sc->sc_flag & DMC_RESTART) == 0) {			sc->sc_dmccs.if_dstate = IFS_HALTING;			ifp->if_flags &= ~IFF_UP;			sc->sc_flag |= DMC_RESTART;			arg = sc->sc_ubinfo & 0x3ffff;			dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM);		} else {			if ( sc->sc_dmccs.if_dstate == IFS_HALTED )				dmcrestart(ifp->if_unit);		}		break;	case SIOCDISABLBACK:	/*	 * place device out of loopback	 */		if ( ! dmcsuser() ) 			return(EACCES);		printf("dmc%d: internal loopback disable requested\n", ifp->if_unit);		ifp->if_flags &= ~IFF_LOOPBACK;		/*		 * kill off the dmc to reset state		 * by generating a procedure error		 */		if ((sc->sc_flag & DMC_RESTART) == 0) {			sc->sc_dmccs.if_dstate = IFS_HALTING;			ifp->if_flags &= ~IFF_UP;			sc->sc_flag |= DMC_RESTART;			arg = sc->sc_ubinfo & 0x3ffff;			dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM);		} else {			if ( sc->sc_dmccs.if_dstate == IFS_HALTED )				dmcrestart(ifp->if_unit);		}		break;	case SIOCRDCTRS:	case SIOCRDZCTRS:		/*		 * reading and zeroing line counters		 */	{		int unit = ifp->if_unit;		register struct ctrreq *ctr = (struct ctrreq *)data;		dmc_update_errctrs(sc, (u_char *) &dmc_base[unit].d_base[0]);		bzero(&ctr->ctr_ctrs, sizeof(struct dstat));		ctr->ctr_type = CTR_DDCMP;		ctr->ctr_ddcmp.dst_seconds = (time.tv_sec - sc->sc_ztime) > 0xfffe ? 0xffff : (time.tv_sec - sc->sc_ztime);		ctr->ctr_ddcmp.dst_bytercvd = sc->sc_rxtxctrs[DMCZ_RXBYTE];		ctr->ctr_ddcmp.dst_bytesent = sc->sc_rxtxctrs[DMCZ_TXBYTE];		ctr->ctr_ddcmp.dst_blockrcvd = sc->sc_rxtxctrs[DMCZ_RXBLOK];		ctr->ctr_ddcmp.dst_blocksent = sc->sc_rxtxctrs[DMCZ_TXBLOK];		/* outbound erros */		if ( sc->sc_errctrs[DMCZ_RXHCRC] ) {			ctr->ctr_ddcmp.dst_outbound_bm |= (1 << CTR_HDRCRC);		}		if ( sc->sc_errctrs[DMCZ_RXDCRC] ) {			ctr->ctr_ddcmp.dst_outbound_bm |= (1 << CTR_DATCRC);		}		if ( (short) (ctr->ctr_ddcmp.dst_outbound = (sc->sc_errctrs[DMCZ_RXHCRC] + sc->sc_errctrs[DMCZ_RXDCRC])) > 0x0ff )			ctr->ctr_ddcmp.dst_outbound = 0x0ff;		/* inbound errors */		if ( sc->sc_errctrs[DMCZ_TXHCRC] ) {			ctr->ctr_ddcmp.dst_inbound_bm |= (1 << CTR_HDRCRC);		}		if ( sc->sc_errctrs[DMCZ_TXDCRC] ) {			ctr->ctr_ddcmp.dst_inbound_bm |= (1<< CTR_DATCRC);		}		if ( (short) (ctr->ctr_ddcmp.dst_inbound = (sc->sc_errctrs[DMCZ_TXHCRC] + sc->sc_errctrs[DMCZ_TXDCRC])) > 0x0ff )			ctr->ctr_ddcmp.dst_outbound = 0x0ff;		/* buffer unavailable */		if (ctr->ctr_ddcmp.dst_remotebuf = sc->sc_errctrs[DMCZ_RXNOBUF] ) {			ctr->ctr_ddcmp.dst_remotebuf_bm |= (1 << CTR_BUFUNAVAIL);		}		if (ctr->ctr_ddcmp.dst_localbuf = sc->sc_errctrs[DMCZ_TXNOBUF] ) {			ctr->ctr_ddcmp.dst_localbuf_bm |= (1 << CTR_BUFUNAVAIL);		}		ctr->ctr_ddcmp.dst_remotetmo = sc->sc_errctrs[DMCZ_REMOTETMO];		ctr->ctr_ddcmp.dst_localtmo = sc->sc_errctrs[DMCZ_LOCALTMO];		if ( cmd == SIOCRDZCTRS ) {			sc->sc_ztime = time.tv_sec;			bzero(&sc->sc_rxtxctrs[DMCZ_RXBYTE], sizeof(sc->sc_rxtxctrs));			bzero(sc->sc_errctrs, sizeof(sc->sc_errctrs));		}		break;	}	case SIOCSIFADDR:		ifp->if_flags |= IFF_UP;		if ((ifp->if_flags & IFF_RUNNING) == 0)			dmcinit(ifp->if_unit); 		break;	case SIOCSIFDSTADDR:		if ((ifp->if_flags & IFF_RUNNING) == 0)			dmcinit(ifp->if_unit); 		break;		        default:                error = EINVAL;        }        splx(s);        return(error);}/* * update drivers copy of line error counters */dmc_update_errctrs(sc, base_table)register struct dmc_softc *sc;register u_char *base_table;{	short tmp_cnt;	if ( (tmp_cnt = base_table[DMCD_RXHCRC] - sc->sc_basectrs[DMCZ_RXHCRC]) ) {		if ( tmp_cnt < 0 || (sc->sc_errctrs[DMCZ_RXHCRC] + tmp_cnt) > 0x0ff )			sc->sc_errctrs[DMCZ_RXHCRC] = 0xff;		else			sc->sc_errctrs[DMCZ_RXHCRC] += tmp_cnt;	}	if ( (tmp_cnt = base_table[DMCD_RXDCRC] - sc->sc_basectrs[DMCZ_RXDCRC]) ) {		if ( tmp_cnt < 0 || (sc->sc_errctrs[DMCZ_RXDCRC] + tmp_cnt) > 0x0ff )

⌨️ 快捷键说明

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