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

📄 hwmtm.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 4 页
字号:
				 *	current frame, search for the				 *	EOF bit to complete the frame				 * else				 *	the fragment belongs to the next frame,				 *	exit the loop and process the frame				 */				SK_BREAK() ;				rfsw = 0 ;				if (frag_count) {					break ;				}			}			n += rbctrl & 0xffff ;			r = r->rxd_next ;			frag_count++ ;			rx_used-- ;		} while (!(rbctrl & BMU_EOF)) ;		used_frags = frag_count ;		DB_RX("EOF set in RxD, used_frags = %d ",used_frags,0,5) ;		/* may be next 2 DRV_BUF_FLUSH() can be skipped, because */		/* BMU_ST_BUF will not be changed by the ASIC */		DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;		while (rx_used && !(r->rxd_rbctrl & AIX_REVERSE(BMU_ST_BUF))) {			DB_RX("Check STF bit in %x",(void *)r,0,5) ;			r = r->rxd_next ;			DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;			frag_count++ ;			rx_used-- ;		}		DB_RX("STF bit found",0,0,5) ;		/*		 * The received frame is finished for the process receive		 */		rxd = queue->rx_curr_get ;		queue->rx_curr_get = r ;		queue->rx_free += frag_count ;		queue->rx_used = rx_used ;		/*		 * ASIC Errata no. 7 (STF - Bit Bug)		 */		rxd->rxd_rbctrl &= AIX_REVERSE(~BMU_STF) ;		for (r=rxd, i=frag_count ; i ; r=r->rxd_next, i--){			DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;			dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);		}		smc->hw.fp.err_stats.err_valid++ ;		smc->mib.m[MAC0].fddiMACCopied_Ct++ ;		/* the length of the data including the FC */		len = (rfsw & RD_LENGTH) - 4 ;		DB_RX("frame length = %d",len,0,4) ;		/*		 * check the frame_lenght and all error flags		 */		if (rfsw & (RX_MSRABT|RX_FS_E|RX_FS_CRC|RX_FS_IMPL)){			if (rfsw & RD_S_MSRABT) {				DB_RX("Frame aborted by the FORMAC",0,0,2) ;				smc->hw.fp.err_stats.err_abort++ ;			}			/*			 * check frame status			 */			if (rfsw & RD_S_SEAC2) {				DB_RX("E-Indicator set",0,0,2) ;				smc->hw.fp.err_stats.err_e_indicator++ ;			}			if (rfsw & RD_S_SFRMERR) {				DB_RX("CRC error",0,0,2) ;				smc->hw.fp.err_stats.err_crc++ ;			}			if (rfsw & RX_FS_IMPL) {				DB_RX("Implementer frame",0,0,2) ;				smc->hw.fp.err_stats.err_imp_frame++ ;			}			goto abort_frame ;		}		if (len > FDDI_RAW_MTU-4) {			DB_RX("Frame to long error",0,0,2) ;			smc->hw.fp.err_stats.err_too_long++ ;			goto abort_frame ;		}		/*		 * SUPERNET 3 Bug: FORMAC delivers status words		 * of aborded frames to the BMU		 */		if (len <= 4) {			DB_RX("Frame length = 0",0,0,2) ;			goto abort_frame ;		}		if (len != (n-4)) {			DB_RX("BMU: rx len differs: [%d:%d]",len,n,4);			smc->os.hwm.rx_len_error++ ;			goto abort_frame ;		}		/*		 * Check SA == MA		 */		virt = (u_char far *) rxd->rxd_virt ;		DB_RX("FC = %x",*virt,0,2) ;		if (virt[12] == MA[5] &&		    virt[11] == MA[4] &&		    virt[10] == MA[3] &&		    virt[9] == MA[2] &&		    virt[8] == MA[1] &&		    (virt[7] & ~GROUP_ADDR_BIT) == MA[0]) {			goto abort_frame ;		}		/*		 * test if LLC frame		 */		if (rfsw & RX_FS_LLC) {			/*			 * if pass_llc_promisc is disable			 *	if DA != Multicast or Broadcast or DA!=MA			 *		abort the frame			 */			if (!smc->os.hwm.pass_llc_promisc) {				if(!(virt[1] & GROUP_ADDR_BIT)) {					if (virt[6] != MA[5] ||					    virt[5] != MA[4] ||					    virt[4] != MA[3] ||					    virt[3] != MA[2] ||					    virt[2] != MA[1] ||					    virt[1] != MA[0]) {						DB_RX("DA != MA and not multi- or broadcast",0,0,2) ;						goto abort_frame ;					}				}			}			/*			 * LLC frame received			 */			DB_RX("LLC - receive",0,0,4) ;			mac_drv_rx_complete(smc,rxd,frag_count,len) ;		}		else {			if (!(mb = smt_get_mbuf(smc))) {				smc->hw.fp.err_stats.err_no_buf++ ;				DB_RX("No SMbuf; receive terminated",0,0,4) ;				goto abort_frame ;			}			data = smtod(mb,char *) - 1 ;			/*			 * copy the frame into a SMT_MBuf			 */#ifdef USE_OS_CPY			hwm_cpy_rxd2mb(rxd,data,len) ;#else			for (r=rxd, i=used_frags ; i ; r=r->rxd_next, i--){				n = AIX_REVERSE(r->rxd_rbctrl) & RD_LENGTH ;				DB_RX("cp SMT frame to mb: len = %d",n,0,6) ;				memcpy(data,r->rxd_virt,n) ;				data += n ;			}			data = smtod(mb,char *) - 1 ;#endif			fc = *(char *)mb->sm_data = *data ;			mb->sm_len = len - 1 ;		/* len - fc */			data++ ;			/*			 * SMT frame received			 */			switch(fc) {			case FC_SMT_INFO :				smc->hw.fp.err_stats.err_smt_frame++ ;				DB_RX("SMT frame received ",0,0,5) ;				if (smc->os.hwm.pass_SMT) {					DB_RX("pass SMT frame ",0,0,5) ;					mac_drv_rx_complete(smc, rxd,						frag_count,len) ;				}				else {					DB_RX("requeue RxD",0,0,5) ;					mac_drv_requeue_rxd(smc,rxd,frag_count);				}				smt_received_pack(smc,mb,(int)(rfsw>>25)) ;				break ;			case FC_SMT_NSA :				smc->hw.fp.err_stats.err_smt_frame++ ;				DB_RX("SMT frame received ",0,0,5) ;				/* if pass_NSA set pass the NSA frame or */				/* pass_SMT set and the A-Indicator */				/* is not set, pass the NSA frame */				if (smc->os.hwm.pass_NSA ||					(smc->os.hwm.pass_SMT &&					!(rfsw & A_INDIC))) {					DB_RX("pass SMT frame ",0,0,5) ;					mac_drv_rx_complete(smc, rxd,						frag_count,len) ;				}				else {					DB_RX("requeue RxD",0,0,5) ;					mac_drv_requeue_rxd(smc,rxd,frag_count);				}				smt_received_pack(smc,mb,(int)(rfsw>>25)) ;				break ;			case FC_BEACON :				if (smc->os.hwm.pass_DB) {					DB_RX("pass DB frame ",0,0,5) ;					mac_drv_rx_complete(smc, rxd,						frag_count,len) ;				}				else {					DB_RX("requeue RxD",0,0,5) ;					mac_drv_requeue_rxd(smc,rxd,frag_count);				}				smt_free_mbuf(smc,mb) ;				break ;			default :				/*				 * unknown FC abord the frame				 */				DB_RX("unknown FC error",0,0,2) ;				smt_free_mbuf(smc,mb) ;				DB_RX("requeue RxD",0,0,5) ;				mac_drv_requeue_rxd(smc,rxd,frag_count) ;				if ((fc & 0xf0) == FC_MAC)					smc->hw.fp.err_stats.err_mac_frame++ ;				else					smc->hw.fp.err_stats.err_imp_frame++ ;				break ;			}		}		DB_RX("next RxD is %x ",queue->rx_curr_get,0,3) ;		NDD_TRACE("RHx1",queue->rx_curr_get,0,0) ;		continue ;	/*--------------------------------------------------------------------*/abort_frame:		DB_RX("requeue RxD",0,0,5) ;		mac_drv_requeue_rxd(smc,rxd,frag_count) ;		DB_RX("next RxD is %x ",queue->rx_curr_get,0,3) ;		NDD_TRACE("RHx2",queue->rx_curr_get,0,0) ;	}rx_end:#ifdef	ALL_RX_COMPLETE	mac_drv_all_receives_complete(smc) ;#endif	return ;	/* lint bug: needs return detect end of function */}static void smt_to_llc(smc,mb)struct s_smc *smc ;SMbuf *mb ;{	u_char	fc ;	DB_RX("send a queued frame to the llc layer",0,0,4) ;	smc->os.hwm.r.len = mb->sm_len ;	smc->os.hwm.r.mb_pos = smtod(mb,char *) ;	fc = *smc->os.hwm.r.mb_pos ;	(void)mac_drv_rx_init(smc,(int)mb->sm_len,(int)fc,		smc->os.hwm.r.mb_pos,(int)mb->sm_len) ;	smt_free_mbuf(smc,mb) ;}/* *	BEGIN_MANUAL_ENTRY(hwm_rx_frag) *	void hwm_rx_frag(smc,virt,phys,len,frame_status) * * function	MACRO		(hardware module, hwmtm.h) *		This function calls dma_master for preparing the *		system hardware for the DMA transfer and initializes *		the current RxD with the length and the physical and *		virtual address of the fragment. Furthermore, it sets the *		STF and EOF bits depending on the frame status byte, *		switches the OWN flag of the RxD, so that it is owned by the *		adapter and issues an rx_start. * * para	virt	virtual pointer to the fragment *	len	the length of the fragment *	frame_status	status of the frame, see design description * * NOTE:	It is possible to call this function with a fragment length *		of zero. * *	END_MANUAL_ENTRY */void hwm_rx_frag(smc,virt,phys,len,frame_status)struct s_smc *smc ;char far *virt ;u_long phys ;int len ;int frame_status ;{	struct s_smt_fp_rxd volatile *r ;	u_int	rbctrl ;	NDD_TRACE("RHfB",virt,len,frame_status) ;	DB_RX("hwm_rx_frag: len = %d, frame_status = %x\n",len,frame_status,2) ;	r = smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put ;	r->rxd_virt = virt ;	r->rxd_rbadr = AIX_REVERSE(phys) ;	rbctrl = AIX_REVERSE( (((u_long)frame_status &		(FIRST_FRAG|LAST_FRAG))<<26) |		(((u_long) frame_status & FIRST_FRAG) << 21) |		BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len) ;	r->rxd_rbctrl = rbctrl ;	DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;	outpd(ADDR(B0_R1_CSR),CSR_START) ;	smc->hw.fp.rx_q[QUEUE_R1].rx_free-- ;	smc->hw.fp.rx_q[QUEUE_R1].rx_used++ ;	smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put = r->rxd_next ;	NDD_TRACE("RHfE",r,AIX_REVERSE(r->rxd_rbadr),0) ;}#ifndef	NDIS_OS2/* *	BEGIN_MANUAL_ENTRY(mac_drv_rx_frag) *	int mac_drv_rx_frag(smc,virt,len) * * function	DOWNCALL	(hwmtm.c) *		mac_drv_rx_frag fills the fragment with a part of the frame. * * para	virt	the virtual address of the fragment *	len	the length in bytes of the fragment * * return 0:	success code, no errors possible * *	END_MANUAL_ENTRY */int mac_drv_rx_frag(smc,virt,len)struct s_smc *smc ;void far *virt ;int len ;{	NDD_TRACE("RHSB",virt,len,smc->os.hwm.r.mb_pos) ;	DB_RX("receive from queue: len/virt: = %d/%x",len,virt,4) ;	memcpy((char far *)virt,smc->os.hwm.r.mb_pos,len) ;	smc->os.hwm.r.mb_pos += len ;	NDD_TRACE("RHSE",smc->os.hwm.r.mb_pos,0,0) ;	return(0) ;}#endif/* *	BEGINN_MANUAL_ENTRY(mac_drv_clear_rx_queue) * * void mac_drv_clear_rx_queue(smc) * struct s_smc *smc ; * * function	DOWNCALL	(hardware module, hwmtm.c) *		mac_drv_clear_rx_queue is called by the OS-specific module *		after it has issued a card_stop. *		In this case, the frames in the receive queue are obsolete and *		should be removed. For removing mac_drv_clear_rx_queue *		calls dma_master for each RxD and mac_drv_clear_rxd for each *		receive buffer. * * NOTE:	calling sequence card_stop: *		CLI_FBI(), card_stop(), *		mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(), * * NOTE:	The caller is responsible that the BMUs are idle *		when this function is called. * *	END_MANUAL_ENTRY */void mac_drv_clear_rx_queue(smc)struct s_smc *smc ;{	struct s_smt_fp_rxd volatile *r ;	struct s_smt_fp_rxd volatile *next_rxd ;	struct s_smt_rx_queue *queue ;	int frag_count ;	int i ;	if (smc->hw.hw_state != STOPPED) {		SK_BREAK() ;		SMT_PANIC(smc,HWM_E0012,HWM_E0012_MSG) ;		return ;	}	queue = smc->hw.fp.rx[QUEUE_R1] ;	DB_RX("clear_rx_queue",0,0,5) ;	/*	 * dma_complete and mac_drv_clear_rxd for all RxDs / receive buffers	 */	r = queue->rx_curr_get ;	while (queue->rx_used) {		DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;		DB_RX("switch OWN bit of RxD 0x%x ",r,0,5) ;		r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;		frag_count = 1 ;		DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;		r = r->rxd_next ;		DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;		while (r != queue->rx_curr_put &&			!(r->rxd_rbctrl & AIX_REVERSE(BMU_ST_BUF))) {			DB_RX("Check STF bit in %x",(void *)r,0,5) ;			r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;			DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;			r = r->rxd_next ;			DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;			frag_count++ ;		}		DB_RX("STF bit found",0,0,5) ;		next_rxd = r ;		for (r=queue->rx_curr_get,i=frag_count; i ; r=r->rxd_next,i--){			DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;			dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);		}		DB_RX("mac_drv_clear_rxd: RxD %x frag_count %d ",			(void *)queue->rx_curr_get,frag_count,5) ;		mac_drv_clear_rxd(smc,queue->rx_curr_get,frag_count) ;		queue->rx_curr_get = next_rxd ;		queue->rx_used -= frag_count ;		queue->rx_free += frag_count ;	}}/*	-------------------------------------------------------------	SEND FUNCTIONS:	-------------------------------------------------------------*//* *	BEGIN_MANUAL_ENTRY(hwm_tx_init) *	int hwm_tx_init(smc,fc,frag_count,frame_len,frame_status) * * function	DOWN_CALL	(hardware module, hwmtm.c) *		hwm_tx_init checks if the frame can be sent through the *		corresponding send queue. * * para	fc	the frame control. To determine through which *		send queue the frame should be transmitted. *		0x50 - 0x57:	asynchronous LLC frame *		0xD0 - 0xD7:	synchronous LLC frame *		0x41, 0x4F:	SMT frame to the network *		0x42:		SMT frame to the network and to the local SMT *		0x43:		SMT frame to the local SMT *	frag_count	count of the fragments for this frame *	frame_len	length of the frame *	frame_status	status of the frame, the send queue bit is already *			specified * * return		frame_status * *	END_MANUAL_ENTRY */int hwm_tx_init(smc,fc,frag_count,frame_len,frame_status)struct	s_smc *smc ;u_char fc ;int frag_count ;int frame_len ;int frame_status ;{	NDD_TRACE("THiB",fc,frag_count,frame_len) ;	smc->os.hwm.tx_p = smc->hw.fp.tx[frame_status & QUEUE_A0] ;	smc->os.hwm.tx_descr = TX_DESCRIPTOR | (((u_long)(frame_len-1)&3)<<27) ;	smc->os.hwm.tx_len = frame_len ;	DB_TX("hwm_tx_init: fc = %x, len = %d",fc,frame_len,3) ;	if ((fc & ~(FC_SYNC_BIT|FC_LLC_PRIOR)) == FC_ASYNC_LLC) {		frame_status |= LAN_TX ;	}	else {		switch (fc) {		case FC_SMT_INFO :		case FC_SMT_NSA :			frame_status |= LAN_TX ;			break ;		case FC_SMT_LOC :			frame_status |= LOC_TX ;			break ;		case FC_SMT_LAN_LOC :			frame_status |= LAN_TX | LOC_TX ;			break ;		default :			SMT_PANIC(smc,HWM_E0010,HWM_E0010_MSG) ;		}	}	if (!smc->hw.mac_ring_is_up) {		frame_status &= ~LAN_TX ;		frame_status |= RING_DOWN ;		DB_TX("Ring is down: terminate LAN_TX",0,0,2) ;	}	if (frag_count > smc->os.hwm.tx_p->tx_free) {#ifndef	NDIS_OS2		mac_drv_clear_txd(smc) ;		if (frag_count > smc->os.hwm.tx_p->tx_free) {			DB_TX("Out of TxDs, terminate LAN_TX",0,0,2) ;			frame_status &= ~LAN_TX ;			frame_status |= OUT_OF_TXD ;		}#else		DB_TX("Out of TxDs, terminate LAN_TX",0,0,2) ;		frame_status &= ~LAN_TX ;		frame_status |= OUT_OF_TXD ;#endif	}	DB_TX("frame_status = %x",frame_status,0,3) ;	NDD_TRACE("THiE",frame_status,smc->os.hwm.tx_p->tx_free,0) ;	return(frame_status) ;}/* *	BEGIN_MANUAL_ENTRY(hwm_tx_frag) *	void hwm_tx_frag(smc,virt,phys,len,frame_status) * * function	DOWNCALL	(hardware module, hwmtm.c) *		If the frame should be sent to the LAN, this function calls *		dma_master, fills the current TxD with the virtual and the *		physical address, sets the STF and EOF bits dependent on *		the frame status, and requests the BMU to start the *		transmit. *		If the frame should be sent to the local SMT, an SMT_MBuf *		is allocated if the FIRST_FRAG bit is set in the frame_status. *		The fragment of the frame is copied into the SMT MBuf. *		The function smt_received_pack is called if the LAST_FRAG *		bit is set in the frame_status word. * * para	virt	virtual pointer to the fragment *	len	the length of the fragment *	frame_status	status of the frame, see design description * * return	nothing returned, no parameter is modified * * NOTE:	It is possible to invoke this macro with a fragment length *		of zero. * *	END_MANUAL_ENTRY */void hwm_tx_frag(smc,virt,phys,len,frame_status)struct	s_smc *smc ;char far *virt ;u_long phys ;int len ;int frame_status ;{	struct s_smt_fp_txd volatile *t ;	struct s_smt_tx_queue *queue ;	u_int	tbctrl ;

⌨️ 快捷键说明

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