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

📄 if_dmc.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
	/*	 * Inform owner that device is up.	 */	if ( ifp->if_addr.sa_family != AF_UNSPEC ) {		struct protosw *pr;		sc->sc_dmccs.if_dstate = IFS_RUNNING;		if ((pr=iffamily_to_proto(ifp->if_addr.sa_family)) && pr->pr_ifstate) 			(*pr->pr_ifstate)(ifp, IFS_RUNNING, &sc->sc_dmccs); 	}}/* * Start output on interface.  Get another datagram * to send from the interface queue and map it to * the interface before starting output. * * Must be called at pri 5 */dmcstart(dev)        dev_t dev;{        int unit = minor(dev);        register struct dmc_softc *sc = &dmc_softc[unit];        struct mbuf *m;        register struct dmcbufs *rp;	register int n;        /*         * Dequeue up to NXMT requests and map them to the UNIBUS.         * If no more requests, or no dmc buffers available, just return.         */	n = 0;        for(rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[sc->sc_bufres.nxmt]; rp++ ) {                /* find an available buffer */                if ((rp->flags & DBUF_DMCS) == 0) {                        IF_DEQUEUE(&sc->sc_if.if_snd, m);                        if (m == 0)                                return;                        /* mark it dmcs */                        rp->flags |= (DBUF_DMCS);                        /*                        * Have request mapped to UNIBUS for transmission                        * and start the output.                        */                        rp->cc = dmcput(&sc->sc_ifuba, n, m);			rp->cc &= DMC_CCOUNT;                        sc->sc_oused++;                        dmcload(sc, DMC_WRITE, rp->ubinfo,                                 rp->cc | ((rp->ubinfo>>2)&DMC_XMEM));                }		n++;        }}/* * Utility routine to load the DMC device registers. */dmcload(sc, type, w0, w1)        register struct dmc_softc *sc;        int type, w0, w1;{        register struct dmcdevice *addr;        register int unit, sps;	register struct dmc_command *qp;	unit = sc->sc_if.if_unit;        addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;        sps = splimp();	/* grab a command buffer from the free list */	if((qp = sc->sc_qfreeh) == (struct dmc_command *)0) {		printf("dmc%d: no free command buffer\n", unit);        	splx(sps);		return;	}	DEQUEUE(sc->sc_qfreeh, sc->sc_qfreet);	/* fill in requested info */	qp->qp_cmd = (type | DMC_RQI);	qp->qp_ubaddr = w0;	qp->qp_cc = w1;		if (sc->sc_qactive){	/* command in progress */		if(type == DMC_READ) {			QUEUE_AT_HEAD(qp, sc->sc_qhead, sc->sc_qtail);		} else {			QUEUE_AT_TAIL(qp, sc->sc_qhead, sc->sc_qtail);		}	} else {	/* command port free */		sc->sc_qactive = qp;		addr->bsel0 = qp->qp_cmd;		dmcrint(unit);	}        splx(sps);}/* * DMC interface receiver interrupt. * Ready to accept another command, * pull one off the command queue. */dmcrint(unit)        int unit;{        register struct dmc_softc *sc;        register struct dmcdevice *addr;        register struct dmc_command *qp;	register int n;        addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;        sc = &dmc_softc[unit];	if ((qp = sc->sc_qactive) == (struct dmc_command *) 0) {		printf("dmcrint: no command for dmc%d\n", unit);		return;	}        while (addr->bsel0&DMC_RDYI) {                addr->sel4 = qp->qp_ubaddr;                addr->sel6 = qp->qp_cc;                addr->bsel0 &= ~(DMC_IEI|DMC_RQI);		/* free command buffer */		QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet);                while (addr->bsel0&DMC_RDYI)                        /* can't check for RDYO here 'cause this                           routine isn't reentrant!             */                                ;		/* move on to next command */                if ((sc->sc_qactive = sc->sc_qhead) == (struct dmc_command *)0)                        break;		/* all done */		/* more commands to do, start the next one */		qp = sc->sc_qactive;		DEQUEUE(sc->sc_qhead, sc->sc_qtail);                addr->bsel0 =  qp->qp_cmd;                n = RDYSCAN;                while (n-- > 0)			if ((addr->bsel0&DMC_RDYI) || (addr->bsel2&DMC_RDYO))				break;        }        if (sc->sc_qactive) {                addr->bsel0 |= DMC_IEI|DMC_RQI;                /* VMS does it twice !*$%@# */                addr->bsel0 |= DMC_IEI|DMC_RQI;        }}/* * DMC interface transmitter interrupt. * A transfer may have completed, check for errors. * If it was a read, notify appropriate protocol. * If it was a write, pull the next one off the queue. */dmcxint(unit)        int unit;{        register struct dmc_softc *sc;        register struct ifnet *ifp;        struct uba_device *ui = dmcinfo[unit];        struct dmcdevice *addr;        struct mbuf *m;        struct ifqueue *inq;        int arg, pkaddr, cmd, len;        register struct ifrw *ifrw;        register struct dmcbufs *rp;	register struct ifxmt *ifxp;	struct dmc_header *dh;	int off, resid;	struct protosw *pr;        addr = (struct dmcdevice *)ui->ui_addr;        sc = &dmc_softc[unit];        ifp = &sc->sc_if;	while (addr->bsel2 & DMC_RDYO) {		cmd = addr->bsel2 & 0xff;		arg = addr->sel6 & 0xffff;		/* reconstruct UNIBUS address of buffer returned to us */		pkaddr = ((arg&DMC_XMEM)<<2) | (addr->sel4 & 0xffff);		/* release port */		addr->bsel2 &= ~DMC_RDYO;		switch (cmd & 07) {		case DMC_OUR:			/*			 * A read has completed.  			 * Pass packet to type specific			 * higher-level input routine.			 */			ifp->if_ipackets++;			/*			 * Accumulate statistics for DECnet			 */			if ( (sc->sc_rxtxctrs[DMCZ_RXBYTE] + (arg & DMC_CCOUNT)) > sc->sc_rxtxctrs[DMCZ_RXBYTE] )				sc->sc_rxtxctrs[DMCZ_RXBYTE] += (arg & DMC_CCOUNT); 			if ( sc->sc_rxtxctrs[DMCZ_RXBLOK] != 0xffffffff )				sc->sc_rxtxctrs[DMCZ_RXBLOK]++;			/* find location in dmcuba struct */			ifrw= &sc->sc_ifuba.ifu_r[0];			for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[sc->sc_bufres.nrcv]; rp++) {				if(rp->ubinfo == pkaddr)					break;				ifrw++;			}			if (rp >= &sc->sc_rbufs[sc->sc_bufres.nrcv])				panic("dmc rcv");			if ((rp->flags & DBUF_DMCS) == 0)				printf("dmc%d: done unalloc rbuf\n", unit);			if ( sc->sc_dmccs.if_nomuxhdr ) {				len = (arg & DMC_CCOUNT); 			} else {				len = (arg & DMC_CCOUNT) - sizeof (struct dmc_header);			}			if (len < 0 || len > DMCMTU) {				ifp->if_ierrors++;				printd("dmc%d: bad rcv pkt addr 0x%x len 0x%x\n",				    unit, pkaddr, len);				goto setup;			}			/* 			 * If using dmc header, then			 * deal with trailer protocol: if type is trailer			 * get true type from first 16-bit word past data.			 * Remember that type was trailer by setting off.			 */			if ( ! sc->sc_dmccs.if_nomuxhdr ) {				dh = (struct dmc_header *)ifrw->ifrw_addr;				dh->dmc_type = ntohs((u_short)dh->dmc_type);#define	dmcdataaddr(dh, off, type)	((type)(((caddr_t)((dh)+1)+(off))))				if (dh->dmc_type >= DMC_TRAILER &&				    dh->dmc_type < DMC_TRAILER+DMC_NTRAILER) {					off = (dh->dmc_type - DMC_TRAILER) * 512;					if (off >= DMCMTU)						goto setup;		/* sanity */					dh->dmc_type = ntohs(*dmcdataaddr(dh, off, u_short *));					resid = ntohs(*(dmcdataaddr(dh, off+2, u_short *)));					if (off + resid > len)						goto setup;		/* sanity */					len = off + resid;				} else					off = 0;			} else				off = 0;			if (len == 0)				goto setup;			/*			 * Pull packet off interface.  Off is nonzero if			 * packet has trailing header; dmc_get 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 = dmc_get(&sc->sc_ifuba, ifrw, len, off, ! (sc->sc_dmccs.if_nomuxhdr));			if (m == 0)				goto setup;			if (off) {				m->m_off += 2 * sizeof (u_short);				m->m_len -= 2 * sizeof (u_short);			}			/*			 * Find protocol to which packet is destined			 */			if ( ! sc->sc_dmccs.if_nomuxhdr ) {				/*				 * Multiplexed - find protocol as a				 * function of packet type				 */				switch (dh->dmc_type) {	#ifdef INET				case DMC_IPTYPE:					if (nINET) {						inq = &ipintrq;						smp_lock(&ipintrq.lk_ifqueue, LK_RETRY);						schednetisr(NETISR_IP);						break;					} else {						printf("dmc%d: unknown address type %d\n",							unit, ifp->if_addr.sa_family);						goto setup;					}#endif				default:				       /*				 	* see if other protocol families defined				 	* and call protocol specific routines.				 	* If no other protocols defined then dump message.				 	*/					if ((pr=iffamily_to_proto(ifp->if_addr.sa_family)) && pr->pr_ifinput) {						if (( m = (struct mbuf *)(*pr->pr_ifinput)(m, ifp, &inq, NULL)) == 0)							goto setup;					} else {	                        		printf("dmc%d: unknown address type %d\n", unit,	                            			ifp->if_addr.sa_family);						m_freem(m);						goto setup;					}				}			}			else			{				/*				 * Not multiplexed - find protocol as a				 * function of family				 */				if ((pr=iffamily_to_proto(ifp->if_addr.sa_family)) && pr->pr_ifinput) {					if (( m = (struct mbuf *)(*pr->pr_ifinput)(m, ifp, &inq, NULL)) == 0) 						goto setup;				} else {	                        	printf("dmc%d: unknown address type %d\n", unit,	                            		ifp->if_addr.sa_family);					m_freem(m);					goto setup;				}			}			if (IF_QFULL(inq)) {				IF_DROP(inq);				m_freem(m);			} else				IF_ENQUEUEIF(inq, m, ifp);                        smp_unlock(&inq->lk_ifqueue);	setup:			/* is this needed? */			rp->ubinfo = ifrw->ifrw_info & 0x3ffff;			dmcload(sc, DMC_READ, rp->ubinfo, 			    ((rp->ubinfo >> 2) & DMC_XMEM) | rp->cc);			break;		case DMC_OUX:			/*			 * A write has completed, start another			 * transfer if there is more data to send.			 */			ifp->if_opackets++;			/*			 * Accumulate statistics for DECnet			 */			if ( (sc->sc_rxtxctrs[DMCZ_TXBYTE] + (arg & DMC_CCOUNT)) > sc->sc_rxtxctrs[DMCZ_TXBYTE] )				sc->sc_rxtxctrs[DMCZ_TXBYTE] += (arg & DMC_CCOUNT); 			if ( sc->sc_rxtxctrs[DMCZ_TXBLOK] != 0xffffffff )				sc->sc_rxtxctrs[DMCZ_TXBLOK]++;			/* find associated dmcbuf structure */			ifxp = &sc->sc_ifuba.ifu_w[0];			for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[sc->sc_bufres.nxmt]; rp++) {				if(rp->ubinfo == pkaddr)					break;				ifxp++;			}			if (rp >= &sc->sc_xbufs[sc->sc_bufres.nxmt]) {				printf("dmc%d: bad packet address 0x%x\n",				    unit, pkaddr);				break;			}			if ((rp->flags & DBUF_DMCS) == 0)				printf("dmc%d: unallocated packet 0x%x\n",				    unit, pkaddr);			/* mark buffer free */			if (ifxp->x_xtofree) {				(void)m_freem(ifxp->x_xtofree);				ifxp->x_xtofree = 0;			}			rp->flags &= ~DBUF_DMCS;			sc->sc_oused--;			sc->sc_nticks = 0;			sc->sc_flag |= DMC_ACTIVE;			break;		case DMC_CNTLO:			arg &= DMC_CNTMASK;			if (arg & DMC_FATAL) {				sc->sc_dmccs.if_dstate = ( arg & DMC_MAINTREC ) ? IFS_ENTEREDMOP : IFS_HALTED;				if (pr=iffamily_to_proto(ifp->if_addr.sa_family)) 					if (pr->pr_ifstate && (*pr->pr_ifstate)(ifp, sc->sc_dmccs.if_dstate, &sc->sc_dmccs)) 						dmcstate(ifp, sc, ui);					else						printd("dmc%d: fatal error, flags=%b\n", unit, arg, CNTLO_BITS);				else					printd("dmc%d: fatal error, flags=%b\n", unit, arg, CNTLO_BITS);				ifp->if_flags &= ~IFF_UP;				if ( ifp->if_addr.sa_family == AF_UNSPEC || sc->sc_dmccs.if_dstate == IFS_STARTING ) {					dmcrestart(unit);				}				break;			}			/* ACCUMULATE STATISTICS */			switch(arg) {			case DMC_NOBUFS:				ifp->if_ierrors++;				if ((sc->sc_nobuf++ % DMC_RPNBFS) == 0)					goto report;				break;			case DMC_DISCONN:				if ((sc->sc_disc++ % DMC_RPDSC) == 0)					goto report;				break;			case DMC_TIMEOUT:				if ((sc->sc_timeo++ % DMC_RPTMO) == 0)					goto report;				break;			case DMC_DATACK:				ifp->if_oerrors++;				if ((sc->sc_datck++ % DMC_RPDCK) == 0)					goto report;				break;			default:				goto report;			}

⌨️ 快捷键说明

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