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

📄 hwmtm.c

📁 MIZI Research, Inc.发布的嵌入式Linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (smc->hw.fp.tx_q[QUEUE_A0].tx_used) {		outpd(ADDR(B0_XA_CSR),CSR_START) ;	}	phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_S]) ;	outpd(ADDR(B5_XS_DA),phys) ;	if (smc->hw.fp.tx_q[QUEUE_S].tx_used) {		outpd(ADDR(B0_XS_CSR),CSR_START) ;	}	/*	 * repair rx queues	 */	phys = repair_rxd_ring(smc,smc->hw.fp.rx[QUEUE_R1]) ;	outpd(ADDR(B4_R1_DA),phys) ;	outpd(ADDR(B0_R1_CSR),CSR_START) ;}static u_long repair_txd_ring(smc,queue)struct s_smc *smc ;struct s_smt_tx_queue *queue ;{	int i ;	int tx_used ;	u_long phys ;	u_long tbctrl ;	struct s_smt_fp_txd volatile *t ;	SK_UNUSED(smc) ;	t = queue->tx_curr_get ;	tx_used = queue->tx_used ;	for (i = tx_used+queue->tx_free-1 ; i ; i-- ) {		t = t->txd_next ;	}	phys = AIX_REVERSE(t->txd_ntdadr) ;	t = queue->tx_curr_get ;	while (tx_used) {		DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;		tbctrl = AIX_REVERSE(t->txd_tbctrl) ;		if (tbctrl & BMU_OWN) {			if (tbctrl & BMU_STF) {				break ;		/* exit the loop */			}			else {				/*				 * repair the descriptor				 */				t->txd_tbctrl &= AIX_REVERSE(~BMU_OWN) ;			}		}		phys = AIX_REVERSE(t->txd_ntdadr) ;		DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;		t = t->txd_next ;		tx_used-- ;	}	return(phys) ;}/* * Repairs the receive descriptor ring and returns the physical address * where the BMU should continue working. * *	o The physical address where the BMU was stopped has to be *	  determined. This is the next RxD after rx_curr_get with an OWN *	  bit set. *	o The BMU should start working at beginning of the next frame. *	  RxDs with an OWN bit set but with a reset STF bit should be *	  skipped and owned by the driver (OWN = 0).  */static u_long repair_rxd_ring(smc,queue)struct s_smc *smc ;struct s_smt_rx_queue *queue ;{	int i ;	int rx_used ;	u_long phys ;	u_long rbctrl ;	struct s_smt_fp_rxd volatile *r ;	SK_UNUSED(smc) ;	r = queue->rx_curr_get ;	rx_used = queue->rx_used ;	for (i = SMT_R1_RXD_COUNT-1 ; i ; i-- ) {		r = r->rxd_next ;	}	phys = AIX_REVERSE(r->rxd_nrdadr) ;	r = queue->rx_curr_get ;	while (rx_used) {		DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;		rbctrl = AIX_REVERSE(r->rxd_rbctrl) ;		if (rbctrl & BMU_OWN) {			if (rbctrl & BMU_STF) {				break ;		/* exit the loop */			}			else {				/*				 * repair the descriptor				 */				r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;			}		}		phys = AIX_REVERSE(r->rxd_nrdadr) ;		DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;		r = r->rxd_next ;		rx_used-- ;	}	return(phys) ;}/*	-------------------------------------------------------------	INTERRUPT SERVICE ROUTINE:	-------------------------------------------------------------*//* *	BEGIN_MANUAL_ENTRY(fddi_isr) *	void fddi_isr(smc) * * function	DOWNCALL	(drvsr.c) *		interrupt service routine, handles the interrupt requests *		generated by the FDDI adapter. * * NOTE:	The operating system dependent module must garantee that the *		interrupts of the adapter are disabled when it calls fddi_isr. * *	About the USE_BREAK_ISR mechanismn: * *	The main requirement of this mechanismn is to force an timer IRQ when *	leaving process_receive() with leave_isr set. process_receive() may *	be called at any time from anywhere! *	To be sure we don't miss such event we set 'force_irq' per default. *	We have to force and Timer IRQ if 'smc->os.hwm.leave_isr' AND *	'force_irq' are set. 'force_irq' may be reset if a receive complete *	IRQ is pending. * *	END_MANUAL_ENTRY */void fddi_isr(smc)struct s_smc *smc ;{	u_long		is ;		/* ISR source */	u_short		stu, stl ;	SMbuf		*mb ;#ifdef	USE_BREAK_ISR	int	force_irq ;#endif#ifdef	ODI2	if (smc->os.hwm.rx_break) {		mac_drv_fill_rxd(smc) ;		if (smc->hw.fp.rx_q[QUEUE_R1].rx_used > 0) {			smc->os.hwm.rx_break = 0 ;			process_receive(smc) ;		}		else {			smc->os.hwm.detec_count = 0 ;			smt_force_irq(smc) ;		}	}#endif	smc->os.hwm.isr_flag = TRUE ;#ifdef	USE_BREAK_ISR	force_irq = TRUE ;	if (smc->os.hwm.leave_isr) {		smc->os.hwm.leave_isr = FALSE ;		process_receive(smc) ;	}#endif	while ((is = GET_ISR() & ISR_MASK)) {		NDD_TRACE("CH0B",is,0,0) ;		DB_GEN("ISA = 0x%x",is,0,7) ;		if (is & IMASK_SLOW) {			NDD_TRACE("CH1b",is,0,0) ;			if (is & IS_PLINT1) {	/* PLC1 */				plc1_irq(smc) ;			}			if (is & IS_PLINT2) {	/* PLC2 */				plc2_irq(smc) ;			}			if (is & IS_MINTR1) {	/* FORMAC+ STU1(U/L) */				stu = inpw(FM_A(FM_ST1U)) ;				stl = inpw(FM_A(FM_ST1L)) ;				DB_GEN("Slow transmit complete",0,0,6) ;				mac1_irq(smc,stu,stl) ;			}			if (is & IS_MINTR2) {	/* FORMAC+ STU2(U/L) */				stu= inpw(FM_A(FM_ST2U)) ;				stl= inpw(FM_A(FM_ST2L)) ;				DB_GEN("Slow receive complete",0,0,6) ;				DB_GEN("stl = %x : stu = %x",stl,stu,7) ;				mac2_irq(smc,stu,stl) ;			}			if (is & IS_MINTR3) {	/* FORMAC+ STU3(U/L) */				stu= inpw(FM_A(FM_ST3U)) ;				stl= inpw(FM_A(FM_ST3L)) ;				DB_GEN("FORMAC Mode Register 3",0,0,6) ;				mac3_irq(smc,stu,stl) ;			}			if (is & IS_TIMINT) {	/* Timer 82C54-2 */				timer_irq(smc) ;#ifdef	NDIS_OS2				force_irq_pending = 0 ;#endif				/*				 * out of RxD detection				 */				if (++smc->os.hwm.detec_count > 4) {					/*					 * check out of RxD condition					 */					 process_receive(smc) ;				}			}			if (is & IS_TOKEN) {	/* Restricted Token Monitor */				rtm_irq(smc) ;			}			if (is & IS_R1_P) {	/* Parity error rx queue 1 */				/* clear IRQ */				outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_P) ;				SMT_PANIC(smc,HWM_E0004,HWM_E0004_MSG) ;			}			if (is & IS_R1_C) {	/* Encoding error rx queue 1 */				/* clear IRQ */				outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_C) ;				SMT_PANIC(smc,HWM_E0005,HWM_E0005_MSG) ;			}			if (is & IS_XA_C) {	/* Encoding error async tx q */				/* clear IRQ */				outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_C) ;				SMT_PANIC(smc,HWM_E0006,HWM_E0006_MSG) ;			}			if (is & IS_XS_C) {	/* Encoding error sync tx q */				/* clear IRQ */				outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_C) ;				SMT_PANIC(smc,HWM_E0007,HWM_E0007_MSG) ;			}		}		/*		 *	Fast Tx complete Async/Sync Queue (BMU service)		 */		if (is & (IS_XS_F|IS_XA_F)) {			DB_GEN("Fast tx complete queue",0,0,6) ;			/*			 * clear IRQ, Note: no IRQ is lost, because			 * 	we always service both queues			 */			outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_F) ;			outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_F) ;			mac_drv_clear_txd(smc) ;			llc_restart_tx(smc) ;		}		/*		 *	Fast Rx Complete (BMU service)		 */		if (is & IS_R1_F) {			DB_GEN("Fast receive complete",0,0,6) ;			/* clear IRQ */#ifndef USE_BREAK_ISR			outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;			process_receive(smc) ;#else			process_receive(smc) ;			if (smc->os.hwm.leave_isr) {				force_irq = FALSE ;			} else {				outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;				process_receive(smc) ;			}#endif		}#ifndef	NDIS_OS2		while ((mb = get_llc_rx(smc))) {			smt_to_llc(smc,mb) ;		}#else		if (offDepth)			post_proc() ;		while (!offDepth && (mb = get_llc_rx(smc))) {			smt_to_llc(smc,mb) ;		}		if (!offDepth && smc->os.hwm.rx_break) {			process_receive(smc) ;		}#endif		if (smc->q.ev_get != smc->q.ev_put) {			NDD_TRACE("CH2a",0,0,0) ;			ev_dispatcher(smc) ;		}#ifdef	NDIS_OS2		post_proc() ;		if (offDepth) {		/* leave fddi_isr because */			break ;		/* indications not allowed */		}#endif#ifdef	USE_BREAK_ISR		if (smc->os.hwm.leave_isr) {			break ;		/* leave fddi_isr */		}#endif		/* NOTE: when the isr is left, no rx is pending */	}	/* end of interrupt source polling loop */#ifdef	USE_BREAK_ISR	if (smc->os.hwm.leave_isr && force_irq) {		smt_force_irq(smc) ;	}#endif	smc->os.hwm.isr_flag = FALSE ;	NDD_TRACE("CH0E",0,0,0) ;}/*	-------------------------------------------------------------	RECEIVE FUNCTIONS:	-------------------------------------------------------------*/#ifndef	NDIS_OS2/* *	BEGIN_MANUAL_ENTRY(mac_drv_rx_mode) *	void mac_drv_rx_mode(smc,mode) * * function	DOWNCALL	(fplus.c) *		Corresponding to the parameter mode, the operating system *		dependent module can activate several receive modes. * * para	mode	= 1:	RX_ENABLE_ALLMULTI	enable all multicasts *		= 2:	RX_DISABLE_ALLMULTI	disable "enable all multicasts" *		= 3:	RX_ENABLE_PROMISC	enable promiscuous *		= 4:	RX_DISABLE_PROMISC	disable promiscuous *		= 5:	RX_ENABLE_NSA		enable rec. of all NSA frames *			(disabled after 'driver reset' & 'set station address') *		= 6:	RX_DISABLE_NSA		disable rec. of all NSA frames * *		= 21:	RX_ENABLE_PASS_SMT	( see description ) *		= 22:	RX_DISABLE_PASS_SMT	(  "	   "	  ) *		= 23:	RX_ENABLE_PASS_NSA	(  "	   "	  ) *		= 24:	RX_DISABLE_PASS_NSA	(  "	   "	  ) *		= 25:	RX_ENABLE_PASS_DB	(  "	   "	  ) *		= 26:	RX_DISABLE_PASS_DB	(  "	   "	  ) *		= 27:	RX_DISABLE_PASS_ALL	(  "	   "	  ) *		= 28:	RX_DISABLE_LLC_PROMISC	(  "	   "	  ) *		= 29:	RX_ENABLE_LLC_PROMISC	(  "	   "	  ) * * *		RX_ENABLE_PASS_SMT / RX_DISABLE_PASS_SMT * *		If the operating system dependent module activates the *		mode RX_ENABLE_PASS_SMT, the hardware module *		duplicates all SMT frames with the frame control *		FC_SMT_INFO and passes them to the LLC receive channel *		by calling mac_drv_rx_init. *		The SMT Frames which are sent by the local SMT and the NSA *		frames whose A- and C-Indicator is not set are also duplicated *		and passed. *		The receive mode RX_DISABLE_PASS_SMT disables the passing *		of SMT frames. * *		RX_ENABLE_PASS_NSA / RX_DISABLE_PASS_NSA * *		If the operating system dependent module activates the *		mode RX_ENABLE_PASS_NSA, the hardware module *		duplicates all NSA frames with frame control FC_SMT_NSA *		and a set A-Indicator and passed them to the LLC *		receive channel by calling mac_drv_rx_init. *		All NSA Frames which are sent by the local SMT *		are also duplicated and passed. *		The receive mode RX_DISABLE_PASS_NSA disables the passing *		of NSA frames with the A- or C-Indicator set. * * NOTE:	For fear that the hardware module receives NSA frames with *		a reset A-Indicator, the operating system dependent module *		has to call mac_drv_rx_mode with the mode RX_ENABLE_NSA *		before activate the RX_ENABLE_PASS_NSA mode and after every *		'driver reset' and 'set station address'. * *		RX_ENABLE_PASS_DB / RX_DISABLE_PASS_DB * *		If the operating system dependent module activates the *		mode RX_ENABLE_PASS_DB, direct BEACON frames *		(FC_BEACON frame control) are passed to the LLC receive *		channel by mac_drv_rx_init. *		The receive mode RX_DISABLE_PASS_DB disables the passing *		of direct BEACON frames. * *		RX_DISABLE_PASS_ALL * *		Disables all special receives modes. It is equal to *		call mac_drv_set_rx_mode successively with the *		parameters RX_DISABLE_NSA, RX_DISABLE_PASS_SMT, *		RX_DISABLE_PASS_NSA and RX_DISABLE_PASS_DB. * *		RX_ENABLE_LLC_PROMISC * *		(default) all received LLC frames and all SMT/NSA/DBEACON *		frames depending on the attitude of the flags *		PASS_SMT/PASS_NSA/PASS_DBEACON will be delivered to the *		LLC layer * *		RX_DISABLE_LLC_PROMISC * *		all received SMT/NSA/DBEACON frames depending on the *		attitude of the flags PASS_SMT/PASS_NSA/PASS_DBEACON *		will be delivered to the LLC layer. *		all received LLC frames with a directed address, Multicast *		or Broadcast address will be delivered to the LLC *		layer too. * *	END_MANUAL_ENTRY */void mac_drv_rx_mode(smc,mode)struct s_smc *smc ;int mode ;{	switch(mode) {	case RX_ENABLE_PASS_SMT:		smc->os.hwm.pass_SMT = TRUE ;		break ;	case RX_DISABLE_PASS_SMT:		smc->os.hwm.pass_SMT = FALSE ;		break ;	case RX_ENABLE_PASS_NSA:		smc->os.hwm.pass_NSA = TRUE ;		break ;	case RX_DISABLE_PASS_NSA:		smc->os.hwm.pass_NSA = FALSE ;		break ;	case RX_ENABLE_PASS_DB:		smc->os.hwm.pass_DB = TRUE ;		break ;	case RX_DISABLE_PASS_DB:		smc->os.hwm.pass_DB = FALSE ;		break ;	case RX_DISABLE_PASS_ALL:		smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = FALSE ;		smc->os.hwm.pass_DB = FALSE ;		smc->os.hwm.pass_llc_promisc = TRUE ;		mac_set_rx_mode(smc,RX_DISABLE_NSA) ;		break ;	case RX_DISABLE_LLC_PROMISC:		smc->os.hwm.pass_llc_promisc = FALSE ;		break ;	case RX_ENABLE_LLC_PROMISC:		smc->os.hwm.pass_llc_promisc = TRUE ;		break ;	case RX_ENABLE_ALLMULTI:	case RX_DISABLE_ALLMULTI:	case RX_ENABLE_PROMISC:	case RX_DISABLE_PROMISC:	case RX_ENABLE_NSA:	case RX_DISABLE_NSA:	default:		mac_set_rx_mode(smc,mode) ;		break ;	}}#endif	/* ifndef NDIS_OS2 *//* * process receive queue */void process_receive(smc)struct s_smc *smc ;{	int i ;	int n ;	int frag_count ;		/* number of RxDs of the curr rx buf */	int used_frags ;		/* number of RxDs of the curr frame */	struct s_smt_rx_queue *queue ;	/* points to the queue ctl struct */	struct s_smt_fp_rxd volatile *r ;	/* rxd pointer */	struct s_smt_fp_rxd volatile *rxd ;	/* first rxd of rx frame */	u_long rbctrl ;			/* receive buffer control word */	u_long rfsw ;			/* receive frame status word */	u_short rx_used ;	u_char far *virt ;	char far *data ;	SMbuf *mb ;	u_char fc ;			/* Frame control */	int len ;			/* Frame length */	smc->os.hwm.detec_count = 0 ;	queue = smc->hw.fp.rx[QUEUE_R1] ;	NDD_TRACE("RHxB",0,0,0) ;	for ( ; ; ) {		r = queue->rx_curr_get ;		rx_used = queue->rx_used ;		frag_count = 0 ;#ifdef	USE_BREAK_ISR		if (smc->os.hwm.leave_isr) {			goto rx_end ;		}#endif#ifdef	NDIS_OS2		if (offDepth) {			smc->os.hwm.rx_break = 1 ;			goto rx_end ;		}		smc->os.hwm.rx_break = 0 ;#endif#ifdef	ODI2		if (smc->os.hwm.rx_break) {			goto rx_end ;		}#endif		n = 0 ;		do {			DB_RX("Check RxD %x for OWN and EOF",(void *)r,0,5) ;			DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;			rbctrl = CR_READ(r->rxd_rbctrl) ;			rbctrl = AIX_REVERSE(rbctrl) ;			if (rbctrl & BMU_OWN) {				NDD_TRACE("RHxE",r,rfsw,rbctrl) ;				DB_RX("End of RxDs",0,0,4) ;				goto rx_end ;			}			/*			 * out of RxD detection			 */			if (!rx_used) {				SK_BREAK() ;				SMT_PANIC(smc,HWM_E0009,HWM_E0009_MSG) ;				/* Either we don't have an RxD or all				 * RxDs are filled. Therefore it's allowed				 * for to set the STOPPED flag */				smc->hw.hw_state = STOPPED ;				mac_drv_clear_rx_queue(smc) ;				smc->hw.hw_state = STARTED ;				mac_drv_fill_rxd(smc) ;				smc->os.hwm.detec_count = 0 ;				goto rx_end ;			}			rfsw = AIX_REVERSE(r->rxd_rfsw) ;			if ((rbctrl & BMU_STF) != ((rbctrl & BMU_ST_BUF) <<5)) {				/*				 * The BMU_STF bit is deleted, 1 frame is				 * placed into more than 1 rx buffer				 *				 * skip frame by setting the rx len to 0				 *				 * if fragment count == 0				 *	The missing STF bit belongs to the

⌨️ 快捷键说明

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