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

📄 if_fza.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
			if(fzadebug)				printf("fza%d: size too long %d",unit,totlen);			m_freem(m0);			goto next_m;		}				/* 		 * the last descriptor not own by host		 * put the mbuf back to the queue 		 */		last = index + totlen/XMTSEGSIZE - (((totlen % XMTSEGSIZE) != 0)? 0 : 1 );		if ( sc->tring[last % sc->nrmcxmt].own == FZA_RMC_OWN ) {			IF_PREPEND(&sc->is_if.if_snd, m0); 			sc->tindex = index;			return;		}							/*		 * String the mbuf chain onto the transmit ring entry's		 * buffer segment addresses.		 * Architectures which need to use program I/O to data copy		 * mbuf chain into one or several ( maximum 9 ) RMC transimit		 * rings which are 512 bytes segments 		 */		if(fzadebug > 1 )			printf("fzastart: ready to copy data len %d \n",totlen);		tpstart = tp;		{		register int tleft = 512 , mleft;		register  caddr_t mptr, tptr;		int space;		int	oindex, nring = 1;		u_long	rmc;			 					/*		 *	rleft : space left for current RMC XMT ring		 *	mleft : bytes left for copying in current mbuf 		 */		m = m0;		tptr = (caddr_t)FZAXMTADDR(tp,sc->basereg); 		oindex = index ;		while (m) {			mleft = m->m_len ;			mptr = mtod(m, caddr_t);			while (mleft) { 				space = MIN(tleft,mleft); 				fzacpy(mptr, tptr , space );				tptr   +=  space ;					mptr   += space ;				mleft  -= space  ;  				tleft  -= space ;				if (tleft == 0 && mleft > 0 ) {					index = ++index % sc->nrmcxmt ;					sc->tring[index].own = FZA_RMC_OWN;					sc->tring[index].rmc = 0;					if(index == 0 )						tptr = (caddr_t)FZAXMTADDR(&sc->tring[index],sc->basereg);					tleft = 512;					nring++;				}				}						m = m->m_next;		}		/*		 * need more than one XMT rings		 */		if( nring > 1 ) { 			sc->tring[index].rmc = FZA_EOP ;			tpstart->rmc = FZA_SOP | FZA_XMT_VBC | totlen ;			} else			tpstart->rmc = FZA_SOP | FZA_EOP | FZA_XMT_VBC | totlen ;			/*		 * save the mbuf chain		 */		tpstart->xmt_mbuf = m0;		tpstart->own = FZA_RMC_OWN;				/* 		 * this is try to slove the RMC pipe line problem		 */		tmp = tpstart->own ; 		if(fzadebug > 1)			printf("fzastart index %d rmc 0x%x \n",index,tpstart->own);		}		sc->nxmit++;		ifp->if_flags |= IFF_OACTIVE ;		/*		 * Advise the port that a new transmit packet is pending		 */		sc->reg_ctla |= XMT_POLL ; 		wbflush();	}	sc->tindex = index;}/* * FZA device interrupt handler */fzaintr(unit)	int unit;{	register struct fza_softc *sc = &fza_softc[unit];	register FZASMTRING *smttp;	register FZAXMTRING *tp;	register int index;	struct mbuf *m0;	struct ifnet *ifp = &sc->is_if;	u_short csr ; 	int s = splimp();	csr = sc->reg_intr;	/* clear the interrupt event register */	sc->reg_intr = csr;		/*	 * Lock softc, since we will be updating the per-unit ring pointers	 * and active ring entry counts frequently.	 */	smp_lock(&sc->lk_fza_softc, LK_RETRY);	/*	 * See if we got here due to a port state change interrupt. 	 */	if (csr & STATE_CHG )  {		switch ((sc->reg_status & ADAPTER_STATE)) {    			case STATE_HALTED :					printf("fza%d: port in the Halt State -> ",unit);					switch(sc->reg_status & ID_FIELD ) {						case HALT_UNKNOWN:							printf("Unknown reason\n");							break;						case HALT_HOST_DIRECTED:							printf("Host request to halt \n");							break;						case HALT_HBUS_PARITY:							printf("Host Maxbus parity errors \n");							break;						case HALT_HNXM:							printf("Host Non-exist Memory \n");							break;						case HALT_ADAP_SW_FAULT:							printf("Adapter software fault\n");							break;							case HALT_ADAP_HW_FAULT:							printf("Adapter hardware fault\n");							break;							case HALT_CNS_PC_TEST:							printf("CNS PC trace path test\n");							sc->flag = FZA_PC_TRACED ;							break;						case HALT_CNS_SW_FAULT:							printf("CNS software fault\n");							break;						case HALT_CNS_HW_FAULT:							printf("CNS hardware fault\n");							break;						default:							printf("unknown halt id %d\n",sc->reg_status & ADAPTER_STATE);							break;					}					{						struct el_rec *elrp;											if((elrp = ealloc(sizeof(struct el_fza), EL_PRILOW))) {							struct el_fza *elbod = &elrp->el_body.el_fza;							bcopy(((char *)(sc->basereg + FZA_DLU_ADDR )),elbod,sizeof(structel_fza));							LSUBID(elrp,ELCT_DCNTL,ELFZA,0,0,unit,(sc->reg_status & ID_FIELD));						} 						EVALID(elrp);					}					/*					 * This is used for HALT recovrey.					 * It will bring back the					 * RUNNING state that help the					 * link unavilable before the 					 * adapter change to HALT state					 * case.					 */					if (!(ifp->if_flags & IFF_RUNNING)) 						ifp->if_flags |= IFF_RUNNING ;					fzareset(unit);					break;			case STATE_RESET:				if(fzadebug)					cprintf("fza%d: port in the Resetting State \n",unit);				break;			case STATE_UNINITIALIZED:				 if(fzadebug)                                        cprintf("fza%d: port in the UninitialiedState \n",unit);                                break; 			case STATE_INITIALIZED:				if(fzadebug)                                        cprintf("fza%d: port in the Initialized State \n",unit);                                break;			case STATE_RUNNING:				if(fzadebug)                                        cprintf("fza%d: port in the Running  State \n",unit);                                break;			case STATE_MAINTENANCE:				if(fzadebug)                                        cprintf("fza%d: port in the Maintenance  State \n",unit);                                break;			default: 				printf("fza%d: Undefined state id  %d \n", unit, sc->reg_status & ADAPTER_STATE  );				break;			}		/*		 * turn off the interface because of unrecovery errors		 */		smp_unlock(&sc->lk_fza_softc);		splx(s);		return;	}		/*	 * See if we get the FLUSH_TX interrupt. If so, the driver	 * will return the ownership of all pending SMT XMT buffer back	 * to the adapter and turn on the DTP bit in all the Tx descriptors 	 * which is owned by the RMC 	 */	if(csr & FLUSH_TX) {		if(fzadebug)			printf("fza%d: flush the XMT buffer \n",unit);		for ( index = sc->tsmtindex, smttp = &sc->smttring[index] ;				 (smttp->own & FZA_HOST_OWN); 			index = index++ % sc->nsmtxmt,smttp = &sc->smttring[index] )  				smttp->own &= ~(FZA_HOST_OWN);		sc->tsmtindex = index;		/*		 * Clean up the Tx ring		 */ 		for ( index = sc->tindex - 1  , tp = &sc->tring[index] ; 			(index != sc->tindex) && (tp->own & FZA_RMC_OWN) ;) { 			tp->rmc |= FZA_XMT_DTP ;			if(--index < 0 )				index =  sc->nrmcxmt-1;			tp = &sc->tring[index];		}		sc->ltindex = sc->tindex - 1 ;		sc->nxmit = 0;		/*		 * notice adapter the flush was done		 */		sc->reg_ctla |= FLUSH_DONE;		wbflush();		smp_unlock(&sc->lk_fza_softc);		splx(s);		return;	}				/*	 * See if we get the LINK STATUS CHANGE interrupt. If so,	 * we need to turn off or turn on the interface 	 */	if (csr & LINK_STATUS_CHG) {		if(fzadebug)			printf("fza%d: LINK STATE CHANGE \n",unit);		if (sc->reg_status & LINK_AVAILABLE ) {				if (!(ifp->if_flags & IFF_RUNNING)) {				ifp->if_flags |= IFF_RUNNING ;				cprintf("fza%d: LINK available \n",unit);				}		} else {			if (ifp->if_flags & IFF_RUNNING ) {				ifp->if_flags &= ~IFF_RUNNING;				cprintf("fza%d: LINK unavailable \n",unit);				/* 		 		 * drop packets on the transmit queue		 		 */					while(sc->is_if.if_snd.ifq_head) {					IF_DEQUEUE(&sc->is_if.if_snd, m0);					m_freem(m0);				}			} 		}	}		if (csr & RCV_POLL)  /* receive interrupt */		fzarint(unit);	if (csr & XMT_PKT_DONE) /* transmit done interrupt */ 		fzatint(unit);	if (csr & CMD_DONE ) /* command done interrupt */ 		fzacmdint(unit);	if (csr & SMT_XMT_POLL) /* SMT transmit done interrupt */ 		fzasmtint(unit);	if (csr & UNS_POLL ) {  /* unsolicited event interrupt */		register int index;		register FZAUNSRING *up;			for(index = sc->unsindex, up= &sc->unsring[index];				(up->own) ; index = ++index % NFZAUNS, 					up = &sc->unsring[index] ) {		/*		 * process the unsolicited ring		 */			if(fzadebug)				printf("fza%d: Unsolicited Event -> ",unit);			else 				mprintf("fza%d: Unsolicited Event -> ",unit);			switch(up->status_id) {				case UNS_UNDEFINED:					if(fzadebug)						printf(" Undefined \n");					else						mprintf(" Undefined \n");					break;				case UNS_RINGINIT:					if(fzadebug)						printf(" Ring Init Initiated \n");					else						mprintf(" Ring Init Initiated \n");					break;				case UNS_RINGINITRCV:					if(fzadebug)						printf(" Ring Init Received \n");					else 						mprintf(" Ring Init Received \n");					break;				case UNS_RINGBEACONINIT:					if(fzadebug)						printf(" Ring Beaconing Initiated \n");					else						mprintf(" Ring Beaconing Initiated \n");					break;				case UNS_DUPADDR:					if(fzadebug)						printf(" Duplicate Address Detected \n");					else						mprintf(" Duplicate Address Detected \n");					break;				case UNS_DUPTOKEN:					if(fzadebug)						printf(" Duplicated Token Detected \n");					else						mprintf(" Duplicated Token Detected \n");					break;				case UNS_RINGPURGEERR:					if(fzadebug)						printf(" Ring Purge Error \n");					else						mprintf(" Ring Purge Error \n");					break;				case UNS_BRIDGESTRIPERR:					if(fzadebug)						printf(" Bridge Strip Error \n");					else						mprintf(" Bridge Strip Error \n");					break;				case UNS_RINGOPOSC:					if(fzadebug)						printf(" Ring Op Oscillation \n");					else						mprintf(" Ring Op Oscillation \n");					break;				case UNS_DIRECTEDBEACON:					if(fzadebug)						printf(" Directed Beacon Received \n");					else						mprintf(" Directed Beacon Received \n");					break;				case UNS_PCINIT:					if(fzadebug)						printf("PC Trace Initiated \n"); 					else						mprintf("PC Trace Initiated \n"); 						break;				case UNS_PCRCV:					if(fzadebug)						printf("PC Trace Received \n");					else						mprintf("PC Trace Received \n");					break;				case UNS_XMT_UNDERRUN:					if(fzadebug)						printf("Transmit Underrun \n");					else						mprintf("Transmit Underrun \n");											break;				case UNS_XMT_FAILURE:					if(fzadebug)						printf("Transmit Failure \n");					else 						mprintf("Transmit Failure \n");					break;				case UNS_RCV_OVERRUN:					if(fzadebug)						printf("Receive Overrun \n");					else						mprintf("Receive Overrun \n");					break;				default:					if(fzadebug)						printf("Unknown event %d \n",up->status_id);					else						mprintf("Unknown event %d \n",up->status_id);					break;			}		up->own = 0 ; /* turn back the ownership to RMC */		}		sc->unsindex = index;	} 						 /* 	  * Dequeue next SMT received packet from queue and copy to SMT RCV ring	  */	{	FZASMTRING *sp = &sc->smtrring[sc->rsmtindex];	register struct mbuf *m;	register caddr_t bp;	int len; 	/*	 * check for something need to be send to the SMT RCV ring	 */	while ( sc->is_smt.ifq_head && (sp->own & FZA_HOST_OWN) ) { 			IF_DEQUEUE(&sc->is_smt, m0);			bp = (caddr_t)(sc->basereg + sp->buf_addr);			len = 0;			m = m0;			while(m) {				fzacpy(mtod(m,caddr_t),bp,m->m_len);				bp += m->m_len;				len += m->m_len;				m = m->m_next;			}			/*			 * use the original RMC descriptor			 */			sp->rmc = FZA_SOP | FZA_EOP | sc->smt_rmc[sc->lsmtrmcindex];			sp->own &= ~FZA_HOST_OWN;			sc->lsmtrmcindex = ++sc->lsmtrmcindex % IFQ_MAXLEN; 			m_freem(m0);			sc->rsmtindex = ++sc->rsmtindex % sc->nsmtrcv;			sp = &sc->smtrring[sc->rsmtindex];		}	/*	 * ask adapter to process this smt frame	 */	sc->reg_ctla |= SMT_RCV_POLL ; 	}			/*	 * Dequeue next transmit request if interface is no longer busy.	 */	if (sc->nxmit <= 0) {		sc->is_if.if_flags &= ~IFF_OACTIVE;		fzastart( unit );	}	/*	 * Drop softc lock and return .	 */	smp_unlock(&sc->lk_fza_softc);	splx(s);}/* * FZA smt interrupt routine */fzasmtint(unit)int unit;{	register struct fza_softc *sc = &fza_softc[unit];	register FZASMTRING *sp;	register FZAXMTRING *tp;	register int index;		FZAXMTRING *tpstart;	caddr_t smtbp,tbp;	int len,last,nring,tlen;	u_long tmp;	/*	 * process SMT XMT frame	 */	for(index = sc->tsmtindex , sp = &sc->smttring[index];		(sp->own & FZA_HOST_OWN); index = ++index % sc->nsmtxmt, 					sp= &sc->smttring[index]) {		tpstart = &sc->tring[sc->tindex];

⌨️ 快捷键说明

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