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

📄 if_dmv.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
                         * Have request mapped to UNIBUS for transmission                         * and start the output.                         */                        rp->cc = dmvput(&sc->sc_ifuba, n, m);			rp->cc &= DMV_CCOUNT;                        sc->sc_oused++;                	dmv_issue_buf(sc, DMV_CMD_TXBUF, 1, rp->ubinfo, rp->cc);                }		n++;        }}/* * Routine to issue mode command. */dmv_issue_mode( sc, mode )register struct dmv_softc *sc;register u_short mode;{	struct dmv_command cmd;	bzero(&cmd, sizeof(cmd));	cmd.qp_cmd = DMV_CMD_MODE;	cmd.qp_data = 0;	cmd.qp_trib = DMV_TRIB_POINT;	cmd.qp_mode = mode;	dmvload(sc, &cmd);}/* * Routine to issue control command. */dmv_issue_ctl( sc, trib, data, ctl )register struct dmv_softc *sc;register u_char trib;register u_short data;register u_short ctl;{	struct dmv_command cmd;	bzero(&cmd, sizeof(cmd));	cmd.qp_cmd = DMV_CMD_CNTL;	cmd.qp_trib = trib;	cmd.qp_data = data;	cmd.qp_ctl = ctl;	dmvload(sc, &cmd);}/* * Routine to issue Tx/Rx buffer command. */dmv_issue_buf( sc, cmd_type, trib, addr, cc )register struct dmv_softc *sc;register u_char cmd_type, trib;register u_int addr;register u_short cc;{	struct dmv_command cmd;	bzero(&cmd, sizeof(cmd));	cmd.qp_cmd = cmd_type | DMV_22BIT;	cmd.qp_trib = trib;	cmd.qp_lowaddr = (u_short) addr;	cmd.qp_hiaddr = (u_short) (addr >> 16);	cmd.qp_cc = cc;	dmvload(sc, &cmd);}/* * Utility routine to load the DMV device registers. */dmvload(sc, cmd)        register struct dmv_softc *sc;	register struct dmv_command *cmd;{        register struct dmvdevice *addr;        register int unit, sps;	register struct dmv_command *qp;        unit = sc->sc_if.if_unit;        addr = (struct dmvdevice *)dmvinfo[unit]->ui_addr;        sps = splimp();	/* grab a command buffer from the free list */	if((qp = sc->sc_qfreeh) == (struct dmv_command *)0) {		printf("dmv%d: no free command buffer\n", unit);        	splx(sps);		return;	}	DEQUEUE(sc->sc_qfreeh, sc->sc_qfreet);	/* fill in requested info and pass to device */	*qp = *cmd;	if (sc->sc_qactive){	/* command in progress */		if(((cmd->qp_cmd & DMV_CMD_MASK) == DMV_CMD_RXBUF) && ! (sc->sc_dmvcs.if_dstate == IFS_STARTING) ) {			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 |= DMV_IEI|DMV_RQI;	}        splx(sps);}/* * DMV interface receiver interrupt. * Ready to accept another command, * pull one off the command queue. */dmvrint(unit)        int unit;{        register struct dmv_softc *sc;        register struct dmvdevice *addr;        register struct dmv_command *qp;        addr = (struct dmvdevice *)dmvinfo[unit]->ui_addr;        sc = &dmv_softc[unit];	if ((qp = sc->sc_qactive) == (struct dmv_command *) 0) {		printd("dmvrint: no command\n");        	addr->bsel2 |= DMV_CMD_CNTL;		addr->sel6 = DMV_CNTL_NOP;		addr->bsel0 &= ~(DMV_RQI | DMV_IEI);		addr->bsel2 &= (DMV_CMD_CNTL | DMV_RDYO);		return;	}	addr->bsel3 = qp->qp_trib;        addr->bsel2 |= (qp->qp_cmd & 0x0f);	switch ( qp->qp_cmd & 0x7 )	{		case DMV_CMD_RXBUF:		case DMV_CMD_TXBUF:                	addr->sel4 = qp->qp_lowaddr;                	addr->sel6 = qp->qp_hiaddr & HIADDR_MASK;                	addr->sel10 = qp->qp_cc & CC_MASK;			break;		case DMV_CMD_CNTL:                	addr->sel4 = qp->qp_data;                	addr->sel6 = qp->qp_ctl & CTL_MASK;			break;		case DMV_CMD_MODE:                	addr->sel6 = qp->qp_mode & MODE_MASK;			break;		default:			printd("dmvrint: bad command = %x\n", qp->qp_cmd);			addr->sel6 = DMV_CNTL_NOP;        		addr->bsel2 |= DMV_CMD_CNTL;			break;	}	/* free command buffer */	QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet);	/* pre-fetch next command */        if ( (sc->sc_qactive = sc->sc_qhead) == (struct dmv_command *)0 ) 		addr->bsel0 &= ~(DMV_RQI | DMV_IEI);	else		DEQUEUE(sc->sc_qhead, sc->sc_qtail);        addr->bsel2 &= ~DMV_RDYI;}/* * DMV 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. */dmvxint(unit)        int unit;{        register struct dmv_softc *sc;        register struct ifnet *ifp;        struct uba_device *ui = dmvinfo[unit];        struct dmvdevice *addr;        struct mbuf *m;        struct ifqueue *inq;        int len, pkaddr;        register struct ifrw *ifrw;        register struct dmvbufs *rp;	register struct ifxmt *ifxp;	struct dmv_header *dh;	struct dmv_command response;	int off, resid;	struct protosw *pr;        addr = (struct dmvdevice *)ui->ui_addr;        sc = &dmv_softc[unit];        ifp = &sc->sc_if;	if ( (response.qp_cmd = addr->bsel2) & DMV_22BIT )		response.qp_cc = addr->sel10;	response.qp_lowaddr = addr->sel4;	response.qp_hiaddr = addr->sel6;	response.qp_trib = addr->bsel3;	/* release port */	addr->bsel2 &= ~DMV_RDYO;	/*	 * analyze response	 */	switch (response.qp_cmd & DMV_CMD_MASK) {		case DMV_RSP_RXBUFOK:			/*			 * A read has completed.  			 * Pass packet to type specific			 * higher-level input routine.			 */			pkaddr = (response.qp_hiaddr << 16) | response.qp_lowaddr;			ifp->if_ipackets++;			/*			 * Accumulate statistics for DECnet			 */			if ( (sc->sc_errctrs.ctr_ddcmp.dst_bytercvd + (response.qp_cc & CC_MASK)) > sc->sc_errctrs.ctr_ddcmp.dst_bytercvd ) 				sc->sc_errctrs.ctr_ddcmp.dst_bytercvd += (response.qp_cc & CC_MASK); 			if (sc->sc_errctrs.ctr_ddcmp.dst_blockrcvd != 0xffffffff)				sc->sc_errctrs.ctr_ddcmp.dst_blockrcvd++;			/* find location in dmvuba 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("dmv%d rcv", unit);			if ((rp->flags & DBUF_DMVS) == 0)				printf("dmv%d: done unalloc rbuf\n", unit);			if ( sc->sc_dmvcs.if_nomuxhdr ) {				len = (response.qp_cc & CC_MASK); 			} else {				len = (response.qp_cc & CC_MASK) - sizeof (struct dmv_header);			}			if (len < 0 || len > DMVMTU) {				ifp->if_ierrors++;				printd("dmv%d: bad rcv pkt addr 0x%x len 0x%x\n",				    unit, pkaddr, len);				goto setup;			}			/* 			 * If using dmv 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_dmvcs.if_nomuxhdr ) {				dh = (struct dmv_header *)ifrw->ifrw_addr;				dh->dmv_type = ntohs((u_short)dh->dmv_type);#define	dmvdataaddr(dh, off, type)	((type)(((caddr_t)((dh)+1)+(off))))				if (dh->dmv_type >= DMV_TRAILER &&				    dh->dmv_type < DMV_TRAILER+DMV_NTRAILER) {					off = (dh->dmv_type - DMV_TRAILER) * 512;					if (off >= DMVMTU)						goto setup;		/* sanity */					dh->dmv_type = ntohs(*dmvdataaddr(dh, off, u_short *));					resid = ntohs(*(dmvdataaddr(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; dmv_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 = dmv_get(&sc->sc_ifuba, ifrw, len, off, ! (sc->sc_dmvcs.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_dmvcs.if_nomuxhdr ) {				/*				 * Multiplexed - find protocol as a				 * function of packet type				 */				switch (dh->dmv_type) {	#ifdef INET				case DMV_IPTYPE:					if (nINET) {						inq = &ipintrq;						smp_lock(&ipintrq.lk_ifqueue, LK_RETRY);						schednetisr(NETISR_IP);						break;					} else {						printf("dmv%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("dmv%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("dmv%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;			if ( sc->sc_dmvcs.if_dstate != IFS_HALTING )                		dmv_issue_buf(sc, DMV_CMD_RXBUF, 1, rp->ubinfo, rp->cc);			else {				rp->flags &= ~DBUF_DMVS;				sc->sc_iused--;			}			break;		case DMV_RSP_RXBUF:			/*			 * An Rx buffer has just been returned unused.  			 */			pkaddr = (response.qp_hiaddr << 16) | response.qp_lowaddr;			/* find location in dmvuba 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("dmv%d rcv", unit);			if ((rp->flags & DBUF_DMVS) == 0)				printf("dmv%d: done unalloc rbuf\n", unit);			rp->flags &= ~DBUF_DMVS;			sc->sc_iused--;			break;		case DMV_RSP_TXBUFOK:			/*			 * A write has completed, start another			 * transfer if there is more data to send.			 */			ifp->if_opackets++;			/*			 * Accumulate statistics for DECnet			 */			if ( (sc->sc_errctrs.ctr_ddcmp.dst_bytesent + (response.qp_cc & CC_MASK)) > sc->sc_errctrs.ctr_ddcmp.dst_bytesent ) 				sc->sc_errctrs.ctr_ddcmp.dst_bytesent += (response.qp_cc & CC_MASK); 			if (sc->sc_errctrs.ctr_ddcmp.dst_blocksent != 0xffffffff)				sc->sc_errctrs.ctr_ddcmp.dst_blocksent++;		case DMV_RSP_TXBUF1:		case DMV_RSP_TXBUF2:			/* find associated dmvbuf structure */			pkaddr = (response.qp_hiaddr << 16) | response.qp_lowaddr;			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("dmv%d: bad packet address 0x%x\n",				    unit, pkaddr);				break;			}			if ((rp->flags & DBUF_DMVS) == 0)				printf("dmv%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_DMVS;			sc->sc_oused--;			sc->sc_nticks = 0;			sc->sc_flag |= DMV_ACTIVE;			break;		case DMV_RSP_CNTL:			dmv_rsp_cntl(sc, &response);			break;		case DMV_RSP_INFO:			if ( response.qp_ctl & (DMV_INFO_READ | DMV_INFO_READZ) ) {				dmv_format_tgss(sc, &response);			} else if ( (response.qp_ctl & KEY_MASK) == DMV_INFO_BUFRET ) {				if ( sc->sc_if.if_addr.sa_family != AF_UNSPEC ) {					struct protosw *pr;					if ((pr=iffamily_to_proto(sc->sc_if.if_addr.sa_family)) && pr->pr_ifstate ) 						(*pr->pr_ifstate)(&sc->sc_if, (sc->sc_dmvcs.if_dstate == IFS_ENTEREDMOP) ? IFS_ENTEREDMOP : IFS_HALTED, &sc->sc_dmvcs); 					dmvstate(&sc->sc_if, sc, ui);				} else		    			sc->sc_dmvcs.if_dstate = IFS_STARTING;									if ( sc->sc_dmvcs.if_dstate == IFS_STARTING ) 					dmvinit(unit);			} else if ( (response.qp_ctl & KEY_MASK) == DMV_INFO_MODEM ) {				printf("dmv%d: information response; modem control = %x\n", unit, response.qp_data);			} else {				printd("dmv%d: unsolicited information response; ctl = %x, data = %x\n", unit, response.qp_ctl, response.qp_data);			}			break;		default:			printd("dmv%d: bad control %o\n", unit, response.qp_cmd);			break;	}	dmvstart(unit);        return;}/* * DMV routine to process control responses. */dmv_rsp_cntl(sc, rsp)register struct dmv_softc *sc;register struct dmv_command *rsp;{	register struct protosw *pr;        register struct uba_device *ui = dmvinfo[sc->sc_if.if_unit];	switch ( rsp->qp_ctl & EVENT_MASK )	{		case DMV_EVT_DISCONN:		case DMV_EVT_CARLOSS:			printdmverr("dmv%d: modem disconnect\n", sc->sc_if.if_unit);			sc->sc_disc++;			sc->sc_if.if_flags &= ~IFF_UP;			sc->sc_dmvcs.if_dstate = IFS_HALTED;			if ( sc->sc_if.if_addr.sa_family != AF_UNSPEC ) {				if ((pr=iffamily_to_proto(sc->sc_if.if_addr.sa_family)) && pr->pr_ifstate ) 					(*pr->pr_ifstate)(&sc->sc_if, sc->sc_dmvcs.if_dstate, &sc->sc_dmvcs); 

⌨️ 快捷键说明

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