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

📄 if_ni.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
		}		/* header + space for DGRLEN buffer names */		ni_data->dg_len = NI_DGRLEN;		ni_data->opcode = DGREC;		ni_data->dg_ptdb_index = 2;		for(j=0; j<NI_RBUF; j++) {		bde = (struct _bd *) ni->ni_pqb->ni.bdt_base;		bde += i+j;/* Need to have 1st buffer be ether_header */		if(j == 0) {			KM_ALLOC(buffer, char *, sizeof(struct ether_header), KM_DEVBUF, KM_NOWAIT);		if (buffer == 0){			printf("ni%d Init out of memory - buffer\n",ni->unit);			return;		}			bde->buf_len = sizeof(struct ether_header);			bde->pt_addr = svtopte(buffer);			bde->offset = (unsigned)buffer&PGOFSET;		} else if ( j == 1) {			KM_ALLOC(buffer, char *,M_CLUSTERSZ,KM_CLUSTER, KM_NOWAIT); 		if (buffer == 0){			printf("ni%d Init out of memory - buffer\n",ni->unit);			return;		}			bde->pt_addr = svtopte(buffer);			bde->offset = (unsigned)buffer&PGOFSET;			bde->buf_len = NI_MAXPACKETSZ;		} else {			cprintf("Too many recv desc");		}		bde->key = 1;		bde->valid = 1;		ni_data->cbufs[j].offset = 0;		ni_data->cbufs[j].s_len = bde->buf_len;		ni_data->cbufs[j].bdt_index = i+j;		ni_data->cbufs[j].buffer_key = 1;		}		if((empty=insqti(ni_data, &ni->freeq2, NI_MAXITRY)) > 0)			printf("recv insqti failed %d\n", i);		else if(empty == QEMPTY) {			while((addr->pc&PC_OWN))				;			addr->pc = PC_FREEQNE|PC_RFREEQ|PC_OWN;			while((addr->pc&PC_OWN))				;		}	}	splx(s);	while((addr->ps&PS_OWN))		;	/* Write Parameters */	{		struct ni_msg *ni_msg;		KM_ALLOC(ni_msg, struct ni_msg *, sizeof(struct ni_msg), KM_DEVBUF, KM_NOW_CL);		if (ni_msg == 0){			printf("ni%d Init out of memory - ni_msg\n",ni->unit);			return;		}		ni_msg->opcode = SNDMSG;		ni_msg->status = 0;		ni_msg->msg_len = sizeof(struct ni_param) + 6;		ni_msg->ni_opcode = NIOP_WPARAM;		/* Someone has set the apa at least once */		if((bcmp(ds->ds_addr, ni_notset, 6) != 0))		bcopy(ds->ds_addr,((struct ni_param *)&ni_msg->text[0])->apa, 6);		((struct ni_param *)&ni_msg->text[0])->flags = NI_PAD;		if((empty=insqti(ni_msg, &ni->comq0, NI_MAXITRY)) > 0)			printf("insqti failed\n");		else if(empty == QEMPTY) {			while((addr->pc&PC_OWN))				; 			addr->pc = PC_CMDQNE|PC_CMDQ0|PC_OWN;			while((addr->pc&PC_OWN))				; 		}	}	{		struct ni_msg *ni_msg;		KM_ALLOC(ni_msg, struct ni_msg *, sizeof(struct ni_msg), KM_DEVBUF, KM_NOW_CL);		if (ni_msg == 0){			printf("ni%d Init out of memory - ni_msg\n",ni->unit);			return;		}		ni_msg->opcode = SNDMSG;		ni_msg->status = 0;		ni_msg->msg_len = sizeof(struct ni_param) + 6;		ni_msg->ni_opcode = NIOP_RCCNTR;		if((empty=insqti(ni_msg, &ni->comq0, NI_MAXITRY)) > 0)			printf("insqti failed\n");		else if(empty == QEMPTY) {			while((addr->pc&PC_OWN))				; 			addr->pc = PC_CMDQNE|PC_CMDQ0|PC_OWN;			while((addr->pc&PC_OWN))				; 		}	}	/* Let all these commands complete */	while((addr->ps & PS_OWN))		;	/* Hardware address not set yet */	while((bcmp(ds->ds_addr, ni_notset, 6) == 0))		;	/* Set up PTDB's */	ni_sptdb(ni,0,1,1,0,1);	/* #1 for send queue returns */	ni_sptdb(ni,ETHERTYPE_IP,2,2,PTDB_UNK|PTDB_BDC,1); /* #2 all incoming */	ds->nxmit = 0;	ifp->if_flags &= ~IFF_OACTIVE;	/* The board is up (ooo rah) */	s = splimp();	smp_lock(&ds->lk_ni_softc, LK_RETRY);	ds->ds_if.if_flags |= IFF_UP|IFF_RUNNING;	nistart(unit);				/* queue output packets */	smp_unlock(&ds->lk_ni_softc);	splx(s);}/* * Setup output on interface. */nistart(unit)	int unit;{	register struct ni *ni = &niinfo[unit];	register struct mbuf *m, *m0;	register struct _bd *bde;	register struct ni_data *nid;	register int len, curindex;	struct mbuf *mprev;	struct ni_softc *ds = &ni_softc[unit];	struct nidevice *addr = (struct nidevice *)ni->ni_regs;        int empty;	if((addr->ps&PS_STATEMASK) != PS_ENABLED) {		cprintf("ni%d state(nistart) %x %x %x %x\n", unit, addr->ps, 			addr->pe, addr->pc, addr->pd);		if((addr->ps&PS_STATEMASK) == PS_UNDEFINED ||		   (addr->ps&PS_STATEMASK) == PS_STOPPED)			nireset(unit);	}	/*	 * Check the queues BEFORE dequeueing an entry	 */	while (ds->ds_if.if_snd.ifq_head && ni->freeq1.flink) {		if((nid = (struct ni_data *)remqhi(&ni->freeq1, NI_MAXITRY))			== (struct ni_data *)QEMPTY)			goto done;		IF_DEQUEUE(&ds->ds_if.if_snd, m0);		m = m0;		bde = (struct _bd *) ni->ni_pqb->ni.bdt_base;		bde += nid->cbufs[0].bdt_index;		mprev = 0;		for (len = 0, curindex = 0; m; curindex++, bde++) {			if ((curindex == (NI_NUMBUF - 2)) &&			    (m->m_next && m->m_next->m_next)) {				int off = 0;				struct mbuf *n, *p = 0;				MGET(n, M_DONTWAIT, MT_DATA);				if (n) {					MCLGET(n, p);					if (p == 0)						m_freem(n);				}				if (!p) {					if((empty=insqti(nid, &ni->freeq1, NI_MAXITRY)) > 0)						printf("insqti failed\n");					else if(empty == QEMPTY) {						while((addr->pc&PC_OWN))							;						addr->pc =  PC_FREEQNE|PC_DFREEQ|PC_OWN;					}					m_freem(m0);					goto done;				}				while (m->m_next) {					bcopy(mtod(m, caddr_t),					      mtod(n, caddr_t)+off,					      (unsigned)m->m_len);					off += m->m_len;					m = m_free(m);				}				n->m_len = off;				n->m_next = m;				m = n;				if (mprev)					mprev->m_next = n;			}			bde->offset = mtod(m, unsigned)&PGOFSET;			bde->pt_addr = svtopte(mtod(m, char *));			bde->buf_len = m->m_len;			bde->valid = 1;			nid->cbufs[curindex].offset = 0;			nid->cbufs[curindex].s_len = bde->buf_len;			nid->cbufs[curindex].chain = 1;			len += m->m_len;			mprev = m;			m = m->m_next;		}		if(len < 64) { /* Last buffer may get something tacked on */			(--bde)->buf_len += 64 - len;			nid->cbufs[curindex-1].s_len += 64 - len;		}		nid->opcode = SNDDG;		nid->R = 1;		nid->status = 0;		nid->dg_ptdb_index = 1;		nid->dg_len = 10 + curindex*8;		nid->cbufs[--curindex].chain = 0;		nid->mbuf_tofree = (unsigned long)m0;		ds->nxmit++;		ds->ds_if.if_flags |= IFF_OACTIVE;		ds->ds_if.if_opackets++;		if((empty=insqti(nid, &ni->comq0, NI_MAXITRY)) > 0)			printf("insqti failed\n");		else if(empty == QEMPTY) {			while((addr->pc&PC_OWN))				;			addr->pc =  PC_CMDQNE|PC_CMDQ0|PC_OWN;		} 	}done:	return;}/* * Command done interrupt. */bvpniintr(unit)	register int unit;{	register struct ni *ni = &niinfo[unit];	register struct nidevice *addr = (struct nidevice *)ni->ni_regs;	register struct ni_softc *ds = &ni_softc[unit];	int s;retry:	if((addr->ps&PS_STATEMASK) != PS_ENABLED) {		if((addr->ps&PS_STATEMASK) == PS_UNDEFINED ||		   (addr->ps&PS_STATEMASK) == PS_STOPPED)			nireset(unit);		addr->ps &= ~PS_SUME;		goto done;	}	/*	 * Check for incoming packets.	 */		s = splimp();		smp_lock(&ds->lk_ni_softc, LK_RETRY);		if(addr->ps&PS_RSQ) {			nirecv(unit);		}	/*	 * Check for outgoing packets.	 */		if (!(ds->ds_if.if_flags & IFF_OACTIVE))			nistart(unit);		smp_unlock(&ds->lk_ni_softc);		splx(s);done:	if(addr->ps & PS_SUME) {		register struct el_rec *elrp;		if ((addr->ps & PS_FQE) && (addr->pd != 0))			/*			 * PS_FQE for other than free queue 0 NOT an			 * error condition.			 */			ni_fqe++;		else {			if((elrp = ealloc(sizeof(struct el_bvp), EL_PRILOW))) {				register struct el_bvp *elbod;				struct biic_regs *nxv;				elbod = &elrp->el_body.elbvp;				nxv = (struct biic_regs *)				      ((char *)(ni->ni_regs) - NI_NI_ADDR);				elbod->bvp_biic_typ = nxv->biic_typ;				elbod->bvp_biic_csr = nxv->biic_ctrl;				elbod->bvp_pcntl = addr->pc;				elbod->bvp_pstatus = addr->ps;				elbod->bvp_perr = addr->pe;				elbod->bvp_pdata = addr->pd;				LSUBID(elrp,ELCT_DCNTL,ELBI_BVP,ELBVP_AIE,				      ni->ni_pqb->ni.piv.bi_node,unit,addr->pe);				EVALID(elrp);			}		}		if((addr->ps&PS_STATEMASK) == PS_UNDEFINED ||		   (addr->ps&PS_STATEMASK) == PS_STOPPED)		goto retry;	}			addr->ps &= ~(PS_OWN|PS_SUME|PS_RSQ);}/* * Ethernet interface receiver interface. */nirecv(unit)	int unit;{	register struct ni *ni = &niinfo[unit];	register struct ni_data *nid;	register struct nidevice *addr = (struct nidevice *)ni->ni_regs;	register struct ni_softc *ds = &ni_softc[unit];	int len, empty;	struct _bd *bde;	/* First guess is that its a data gram recieve */		for(;;) {	if((nid = (struct ni_data *)remqhi(&ni->respq, NI_MAXITRY)) 		>= (struct ni_data *)QEMPTY) 		break;		if(nid->status&PCK_FAIL) {			register struct el_rec *elrp;			if((elrp = ealloc(sizeof(struct el_bvp), EL_PRILOW))) {			register struct el_bvp *elbod;			struct biic_regs *nxv;			elbod = &elrp->el_body.elbvp;			nxv = (struct biic_regs *)				((char *)(ni->ni_regs) - NI_NI_ADDR);			elbod->bvp_biic_typ = nxv->biic_typ;			elbod->bvp_biic_csr = nxv->biic_ctrl;			elbod->bvp_pcntl = addr->pc;			elbod->bvp_pstatus = addr->ps;			elbod->bvp_perr = addr->pe;			elbod->bvp_pdata = addr->pd;			LSUBID(elrp,ELCT_DCNTL,ELBI_BVP,ELBVP_AIE,				ni->ni_pqb->ni.piv.bi_node,unit,nid->status);			EVALID(elrp);			}		}		switch(nid->opcode) {		case DGIREC:		case DGISNT:			break;		case DGREC:			ds->ds_if.if_ipackets++;			bde = (struct _bd *) ni->ni_pqb->ni.bdt_base;			bde += nid->cbufs[0].bdt_index;			if(nid->status&PCK_FAIL)				ds->ds_if.if_ierrors++;			len = 0;			/* Walk buffers & add length */			{ register int curindex = 0;			  register struct _bd *pbde = bde;			while(curindex < NI_RBUF ) {				len += nid->cbufs[curindex].s_len;				nid->cbufs[curindex].s_len = pbde++->buf_len;				if(nid->cbufs[curindex].chain == 0)					break;				curindex++;			}			}			niread(ni, ds, bde, len, 0);			nid->opcode=DGREC;			nid->dg_len = NI_DGRLEN;			nid->status=0;	/* DGREC must end up on freeq2 */			if((empty=insqti(nid, &ni->freeq2, NI_MAXITRY)) > 0)				printf("insqti failed\n");			else if(empty == QEMPTY) {				while((addr->pc&PC_OWN))					;				addr->pc =  PC_FREEQNE|PC_RFREEQ|PC_OWN;			}			break;		case DGSNT:	/* DGSNT must end up on freeq1 */			{			struct mbuf *m = (struct mbuf *)nid->mbuf_tofree;			if (!(--ds->nxmit))				ds->ds_if.if_flags &= ~IFF_OACTIVE;			if(nid->status&PCK_FAIL) {				ds->ds_if.if_oerrors++;				m_freem(m);			}			else {				if(((bcmp(mtod(m, struct ether_header *), ni_multi, 6) == 0)) || (ds->ds_if.if_flags & IFF_PFCOPYALL))					niread(ni, ds, 0, 64, m);				else					m_freem(m);			}			nid->mbuf_tofree = 0;			if((empty=insqti(nid, &ni->freeq1, NI_MAXITRY)) > 0)				printf("insqti failed\n");			else if(empty == QEMPTY) {				while((addr->pc&PC_OWN))					;				addr->pc =  PC_FREEQNE|PC_DFREEQ|PC_OWN;			}			}			break;		case MSGSNT:		case MSGREC:			{ 			struct ni_msg *ni_msg;			ni_msg = (struct ni_msg *)nid;			switch(ni_msg->ni_opcode) {				case NIOP_WPARAM:				case NIOP_RPARAM:				bcopy(((struct ni_param *)&ni_msg->text[0])->apa, ds->ds_addr, 6);				bcopy(((struct ni_param *)&ni_msg->text[0])->dpa, ds->ds_dpaddr, 6);#if NPACKETFILTER > 0				/* tell packet filter about new address */				pfilt_newaddress(ds->ds_ed.ess_enetunit, ds->ds_addr);#endif NPACKETFILTER > 0					break;				case NIOP_RCCNTR:				case NIOP_RDCNTR:				/* User may be waiting for info to come back */					wakeup((caddr_t)ni_msg);					break;				case NIOP_STPTDB:				case NIOP_CLPTDB:				default:					break;			}	/* MSGSNT must end up on freeq0 */			if((empty=insqti(ni_msg, &ni->freeq0, NI_MAXITRY))>0)				printf("insqti failed\n");			else if(empty == QEMPTY) {				while((addr->pc&PC_OWN))					;				addr->pc = PC_FREEQNE|PC_MFREEQ|PC_OWN;			}			}			break;		default:			cprintf("ni%d unknown respq opcode\n", unit);			if((empty=insqti(nid, &ni->freeq0, NI_MAXITRY))>0)				printf("insqti failed\n");			else if(empty == QEMPTY) {				while((addr->pc&PC_OWN))					;				addr->pc = PC_FREEQNE|PC_MFREEQ|PC_OWN;			}			break;		}	}	}/* * Pass a packet to the higher levels. * We deal with the trailer protocol here. */niread(ni, ds, bde, len, swloop)	struct ni *ni;	register struct ni_softc *ds;	register struct _bd *bde;	int len;	struct mbuf *swloop; {    	register struct mbuf *m, *swloop_tmp1;	struct ether_header *eh, swloop_eh;	struct protosw *pr;

⌨️ 快捷键说明

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