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

📄 if_fza.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
		tlen = len = sp->rmc & RMC_PBC_MASK;				/*		 * check the last xmt descriptor 		 */		last = sc->tindex + len/XMTSEGSIZE - (((len % XMTSEGSIZE) != 0) ? 0 : 1);		/*		 * last descriptor not own by host		 */		if( sc->tring[last % sc->nsmtxmt].own & FZA_RMC_OWN ) {			sc->tsmtindex = index ;			return;		} 				/*		 * copy the data from SMT XMT ring to RMC XMT ring		 */		nring = 0;			smtbp = (caddr_t)(sp->buf_addr + sc->basereg); 		while(len > 0) {			tp = &sc->tring[sc->tindex];			tbp = (caddr_t)FZAXMTADDR(tp,sc->basereg);			fzacpy(smtbp,tbp,MIN(len,XMTSEGSIZE));			smtbp += MIN(len,XMTSEGSIZE);			len -= MIN(len,XMTSEGSIZE);                        if(nring) {                                tp->own = FZA_RMC_OWN;                                tp->rmc = 0;			}			sc->tindex = ++sc->tindex % sc->nrmcxmt;			nring++;		}		if(nring > 1 ) {				tpstart->rmc = FZA_SOP | FZA_XMT_VBC | tlen;				if(sc->tindex)					sc->tring[sc->tindex-1].rmc = FZA_EOP ;				else					sc->tring[sc->nrmcxmt-1].rmc = FZA_EOP;		} else 			tpstart->rmc = FZA_SOP | FZA_EOP | FZA_XMT_VBC | tlen;				tpstart->own = FZA_RMC_OWN;		tpstart->xmt_mbuf = (struct mbuf *)0;		tmp = tpstart->own ; 		/*		 * give back the ownership to adapter		 */		sp->own &= ~FZA_HOST_OWN; 		sc->nxmit++;	}	/* 	 * notice the port that one or more transmit packet is pending	 */	sc->reg_ctla |= XMT_POLL;	wbflush();	sc->tsmtindex = index ;}	/* * FZA command interrupt routine */fzacmdint(unit)int unit;{	register struct fza_softc *sc = &fza_softc[unit];	register FZACMDRING *cp;	register FZACMD_BUF *xcmd;	register int index;	struct mbuf *m;	for ( index = (sc->lcmdindex + 1) % NFZACMD, cp = &sc->cmdring[index];		(index != sc->cmdindex ) && (cp->own); 			index = ++index % NFZACMD ,cp = &sc->cmdring[index] ) {		/*		 * process the cmd descriptor		 */		if(cp->status_id == 0 ) { /* command successed */			xcmd = (FZACMD_BUF *) (cp->buf_addr + sc->basereg) ; 			switch(cp->cmdid) {				case CMD_RDCNTR: /* copy the counter*/					if(fzadebug)						sc->fza_debug.cmdcnt.rdcntr++;					bcopy(xcmd,sc->ctrblk,sizeof(struct _fzactrs));					break;				case CMD_STATUS:					if(fzadebug)						sc->fza_debug.cmdcnt.status++;					bcopy(xcmd,sc->statusblk,sizeof(structfzastatus));					break;				case CMD_MODCAM:					if(fzadebug)						sc->fza_debug.cmdcnt.modcam++;					break;				case CMD_SETCHAR:					if(fzadebug)						sc->fza_debug.cmdcnt.setchar++;					break;				case CMD_RDCAM:					if(fzadebug)						sc->fza_debug.cmdcnt.rdcam++;					bcopy(xcmd,&sc->is_multi[0][0],512);	                                        break;				case CMD_MODPROM:					if(fzadebug)						sc->fza_debug.cmdcnt.modprom++;					break;				case CMD_PARAM:					if(fzadebug)						sc->fza_debug.cmdcnt.param++;					break;				case CMD_INIT:					if(fzadebug)						sc->fza_debug.cmdcnt.init++;					break;				case CMD_NOP:						break;				default:					if(fzadebug)						mprintf("fza%d: unknown command id %d\n",unit,cp->cmdid);						break;			}		} else { /* error command */			printf("fza%d: command failed, ",unit);			fzacmdstatus(sc,cp->status_id,unit,"fzacmdint");			}		}	if(index)		sc->lcmdindex = index - 1;	else 		sc->lcmdindex = NFZACMD - 1;}/* * FZA transmit interrupt routine */fzatint(unit)int unit;{	register struct fza_softc *sc = &fza_softc[unit];	register FZAXMTRING *tp;	register struct mbuf *m0;	register int index,len = 0;	struct mbuf *mp;	struct fddi_header *fh;	/*	 * Process all outstanding transmits completed by	 * the port.	 */	for (index = (sc->ltindex + 1)%sc->nrmcxmt ,tp = &sc->tring[index]; 			(sc->nxmit > 0) && !(tp->own & FZA_RMC_OWN) ; 		index = ++index % sc->nrmcxmt, tp = &sc->tring[index]) { 		/* 		 * if this is a start packet, process it. if not, do nothing		 */		if(tp->rmc & FZA_SOP ) { 			/*		 	 * Process xmit descriptor, we have no way to know the		 	 * packet trasnmit status		 	 */			sc->is_if.if_opackets++;			mp = (struct mbuf *)tp->xmt_mbuf;			tp->xmt_mbuf = (struct mbuf *)0;			if( tp->rmc & FZA_XMT_SUCCESS ) {				fstc_bytesent += tp->rmc & RMC_PBC_MASK;				if( fstc_pdusent != 0xffffffff)					fstc_pdusent++;				/*		 	 	 * Loop back any LLC broadcasts we send				 * 				 * mp == 0 that means this is a SMT packet 				 * this packet was copy from SMT XMT ring		 	 	 */				if(mp) { /* LLC packet */					fh = mtod(mp, struct fddi_header *);					if ( (!bcmp(&fh->fddi_dhost[0],						etherbroadcastaddr, 6))						|| (sc->is_if.if_flags & IFF_PFCOPYALL)						) {						m0 = mp;						while (m0) {							len += m0->m_len;							m0 = m0->m_next;						}						fzaread(sc, 0, len, mp);					} else {						if( fh->fddi_dhost[0] & 1 ) {							fstc_mbytesent += tp->rmc & RMC_PBC_MASK;							if(fstc_mpdusent != 0xffffffff)							fstc_mpdusent++;						}						m_freem(mp);					}				}			} else {				if(mp)					m_freem(mp);				sc->is_if.if_oerrors++;			}			sc->nxmit--;		}	}	if(index)		sc->ltindex = index - 1;	/* Last xmit processed */	else		sc->ltindex = sc->nrmcxmt - 1;}	/* * FZA receive interrupt routine  */fzarint(unit)int unit;{	register struct fza_softc *sc = &fza_softc[unit];	register int index,len;	register FZARCVRING *rp;	struct mbuf *m,*m1,*mp;	struct fddi_header *fptr;	struct rmbuf *bp;	int nrcv = 0;	int fddi_type;	/*	 * Process all incoming packets on the receive ring. Stop if	 * we get to the current receive index to avoid locking out	 * the system, but give back one descriptor for each one we	 * process to keep the device busy.	 * 	 * 	 */	for (index = sc->rindex, rp = &sc->rring[index], bp = &sc->rmbuf[index];			(rp->rcv_own & FZA_RCV_OWN) && nrcv < NFZARCV - 1;	     index = sc->rindex = ++index % NFZARCV, rp = &sc->rring[index], bp = &sc->rmbuf[index], nrcv++) {		/*		 * check the DMA RCV status. If no error, process it		 * we only process the LLC and SMT frame for decword		 */		if(!(rp->rmc & FZA_RCV_ERROR)) {			len = rp->rmc & RMC_PBC_MASK  ;			if ( len > FDDIMAX ) { /* Frame too long */				if(fstc_pdulen != 0xffffffff)					fstc_pdulen++;				goto error;			} else {			fptr = (struct fddi_header *)PHYS_TO_K1(bp->phymbufa);				switch (fptr->fddi_fc & ~FDDIFC_Z ) { /* take out the priority */					case FDDIFC_LLC_ASYNC: /* for LLC frame */					case FDDIFC_LLC_SYNC: 						if( len < FDDILLCMIM ) {							if(fzadebug)								printf("fza%d: LLC frame too short - frame len %d",unit,len);						if(fstc_pdulen != 0xffffffff)					  	        fstc_pdulen++;							goto error;						}						fddi_type = FZA_LLC;			/*			 * The length reported by RMC is including one			 * byte Frame Control, real data and 4 bytes CRC. 			 * The driver interprets the frame as 4 bytes			 * FDDI header ( including one byte Frame Control)  			 * and real data. So, we need to decrement one		  	 * for the length. 			 */ 						len--;						break;						case FDDIFC_SMT:	/* for SMT frame */						if( len < FDDISMTMIM) {							if(fzadebug)								printf("fza%d: LLC frame too short - frame len %d",unit,len);							if(fstc_pdulen != 0xffffffff)						  	        fstc_pdulen++;							goto error;						}						fddi_type = FZA_SMT;					/*                                         * mismatch with the firmware                                         * RMC told us the wrong length                                         */						len = len + 3 ;						break;					case FDDIFC_MAC:					default:						if(fzadebug)							mprintf("fza%d: unrecognize frame FC 0x%2x\n",unit,fptr->fddi_fc);							fzanundrop++;						goto error;						break;				}			}							/*			 * Allocate a pair of new mbufs for the current			 * receive descriptor. 			 *			 * Each receive buffer will use two cluster mbufs.			 * 			 * The first cut will be :			 *			 * If the size of packet less than 4K, then the second			 * mbuf will be reused.			 *			 * The second cut will be:			 * 			 * If the size of FDDI frame less than the small			 * mbuf length (which is MLEN = 108), driver will 			 * allocate a small mbuf then data copy the			 * packet to it. This will save a large cluster mbuf. 			 *			 * In addition, if the second mbuf only is used for 			 * less than MLEN size, a small mbuf will be allocated  			 * and data copy the rest of packet from the second 			 * cluster mbuf to this small mbuf.			 * 			 */			if(fzadebug > 1 ) {				printf("fzarint: got packet size %d type",len); 				if(fddi_type == FZA_LLC )					printf(" LLC frame \n");				else					printf(" SMT frame \n");			}			if(len > MLEN ) { 				FZAMCLGET(mp)			} else { 				MGET(mp, M_DONTWAIT, MT_DATA)			}			m = bp->mbufa ; 			if ( mp ) {				if ( len > M_CLUSTERSZ ) { 					FZAMCLGET(m1)					if(m1) {						clean_dcache(PHYS_TO_K0(bp->phymbufa),M_CLUSTERSZ); 						clean_dcache(PHYS_TO_K0(bp->phymbufb),len - M_CLUSTERSZ);						m->m_next = bp->mbufb;						m->m_next->m_len = len - M_CLUSTERSZ;						fzanlarge++;					} else {						m_freem(mp);						fzannombuf++;						goto doinit;					}				} else if ( len > MLEN ) {					m1 = bp->mbufb;					clean_dcache(PHYS_TO_K0(bp->phymbufa),len); 					m->m_len = len;					fzanmiddle++;				} else {					/* 					 * if size < = MLEN					 */					bcopy((PHYS_TO_K1(bp->phymbufa)),mtod(mp,caddr_t),len);					m = mp;					m->m_len = len;					mp = bp->mbufa; 					m1 = bp->mbufb;					fzansmall++;				}				if(fddi_type == FZA_LLC )					fzaread (sc, m, len, (struct mbuf *)0);				else { /* for SMT frame, just queue it */					if(IF_QFULL(&sc->is_smt)){						IF_DROP(&sc->is_smt);						/*						 * increase the system buffer						 * unavailable						 */						sc->reg_ctla = SMT_RCV_OVERFLOW;								fzansmtdrop++;						m_freem(m);					} else {						fzansmtrcvd++;						IF_ENQUEUE(&sc->is_smt,m);						/* Save the RMC descriptor */						sc->smt_rmc[sc->smtrmcindex]= rp->rmc; 						sc->smtrmcindex = ++sc->smtrmcindex % IFQ_MAXLEN;					}				}				fzainitdesc(rp,bp,mp,m1);			} else { 				fzannombuf++;				goto doinit;			}					} else { /* if error happened, paser the RMC descriptor */ 			if(fzadebug)				mprintf("fza%d: recv err x%x\n",unit,rp->rmc);			switch(rp->rmc & FZA_RCV_RCC ) {			case FZA_RCV_OVERRUN: /* frame too long */					if(len == 8192 || len == 8191) 					        fstc_pdulen++;					else {					     if (fzadebug)						printf("xfa%d: RMC FIFO Overflow",unit); 							}									break;			case FZA_RCV_INTERFACE_ERR:/* RMC/MAC interface error*/ 					/*					 * adapter should take care this					 * driver will never see this					 */					printf("fza%d: RMC/MAC interface error",unit);										break;			default:				switch(rp->rmc & FZA_RCV_RCC_rrr) {					case FZA_RCV_RCC_NORMAL:						if(rp->rmc & FZA_RCV_RCC_C) {							fstc_fcserror++;							if(fzadebug)								printf("fza%d: Block Check Error\n",unit); 						} else if ( !(rp->rmc & FZA_RCV_FSC) || (rp->rmc & FZA_RCV_FSB_E)){							fstc_fseerror++;							if(fzadebug)								printf("fza%d: Frame status error\n",unit); 						}						break;					case FZA_RCV_RCC_INVALID_LEN:						fstc_pdualig++;						if(fzadebug)		 							printf("fza%d: Frame Alignment Error\n",unit);						break;					case FZA_RCV_RCC_SA_MATCHED:					case FZA_RCV_RCC_DA_NOMATCHED:					case FZA_RCV_RCC_RMC_ABORT:						if(fzadebug) 							printf("fza%d: Hardware problem \n",unit);						/*						 * go to halt state, log						 * the errors						 */						sc->reg_ctla = HALT;						return;						break;					case FZA_RCV_RCC_FRAGMENT:					case FZA_RCV_RCC_FORMAT_ERR:					case FZA_RCV_MAC_RESET:						if(fzadebug)							printf("fza%d: Fragment or format error or MAC reset\n",unit);						break;					defualt:						if(fzadebug)							printf("fza%d: Wrong RMC descriptor report 0x%x \n",unit,rp->rmc);						break;				}				break;			}	 error:			sc->is_if.if_ierrors++;doinit:			fzainitdesc(rp,bp,bp->mbufa,bp->mbufb);								}	}}/* * FZA read routine. Pass input packets up to higher levels. */fzaread (sc, m, len, swloop)	register struct fza_softc *sc;	register int len;	struct mbuf *m;	struct mbuf *swloop;{	register struct fddi_header *eptr;	register int off, resid;	struct mbuf *swloop_tmp1;	struct ether_header eh;	struct protosw *pr;	struct ifqueue *inq;	/*	 * Not supporting the trailer protocol	 */	if (swloop) {		eptr = mtod(swloop, struct fddi_header *);		if ( swloop->m_len > sizeof(struct fddi_header))			m_adj(swloop, sizeof(struct fddi_header));		else {			MFREE(swloop, swloop_tmp1);			if ( ! swloop_tmp1 )				return;			else				swloop = swloop_tmp1;		}	} else 		eptr = mtod(m, struct fddi_header *);	/*	 * Pull packet off interface. 	 */	if (swloop) {		m = m_copy(swloop, 0, M_COPYALL);		m_freem(swloop);		if (m == 0)			return;	} else {

⌨️ 快捷键说明

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