コード例 #1
0
static void ResetAdapter(struct s_smc *smc)
{

	pr_debug(KERN_INFO "[fddi: ResetAdapter]\n");

	

	card_stop(smc);		

	
	mac_drv_clear_tx_queue(smc);
	mac_drv_clear_rx_queue(smc);

	

	smt_reset_defaults(smc, 1);	

	init_smt(smc, (smc->os.dev)->dev_addr);	

	smt_online(smc, 1);	
	STI_FBI();

	
	skfp_ctl_set_multicast_list_wo_lock(smc->os.dev);
}				
コード例 #2
0
static int skfp_close(struct net_device *dev)
{
	struct s_smc *smc = netdev_priv(dev);
	skfddi_priv *bp = &smc->os;

	CLI_FBI();
	smt_reset_defaults(smc, 1);
	card_stop(smc);
	mac_drv_clear_tx_queue(smc);
	mac_drv_clear_rx_queue(smc);

	netif_stop_queue(dev);
	
	free_irq(dev->irq, dev);

	skb_queue_purge(&bp->SendSkbQueue);
	bp->QueueSkb = MAX_TX_QUEUE_LEN;

	return (0);
}				
コード例 #3
0
void process_receive(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 = le32_to_cpu(CR_READ(r->rxd_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 = le32_to_cpu(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
				 *	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 & cpu_to_le32(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 &= cpu_to_le32(~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_length 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 too 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 = le32_to_cpu(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 */
}