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

📄 rhine_main.c

📁 联想网卡驱动 linux环境下编写 初写驱动的同志参考以下
💻 C
📖 第 1 页 / 共 5 页
字号:
static void rhine_rx_srv(PRHINE_INFO pInfo, int status) {	PRX_DESC				pRD=pInfo->pCurrRD;	struct net_device_stats* pStats=&pInfo->stats;		 	PMAC_REGS				pMacRegs=pInfo->pMacRegs;    for (pRD=pInfo->pCurrRD;    	pRD->rdesc0.f1Owner==OWNED_BY_HOST;pRD=pRD->next) {    	if (pRD->rdesc0.byRSR1 & RSR1_RXOK) {			if (rhine_receive_frame(pInfo, pRD)) {				if (!rhine_alloc_rx_buf(pInfo,pRD)) {					RHINE_PRT(MSG_LEVEL_ERR, KERN_ERR					"%s: can not allocate rx buf\n", pInfo->dev->name);						break;				}			} else {				pStats->rx_errors++;							pStats->rx_dropped++;			}		} else {			pStats->rx_errors++;			if (pRD->rdesc0.byRSR0 & RSR0_CRC)				pStats->rx_crc_errors++;			if (pRD->rdesc0.byRSR0 & RSR0_FAE)				pStats->rx_frame_errors++;			if (pRD->rdesc0.byRSR0 & RSR0_FOV)				pStats->rx_fifo_errors++;			pStats->rx_dropped++;		}				pRD->rdesc0.f1Owner=OWNED_BY_NIC;		if (pInfo->flags & RHINE_FLAGS_FLOW_CTRL)			writeb(1,&pMacRegs->byFlowCR0);		pInfo->dev->last_rx=jiffies;    }    pInfo->pCurrRD=pRD;}#ifdef VMNSstatic void inlinerhine_attach_vmns_info(PRX_DESC pRD,struct sk_buff* skb,U16 wTag) {	PVMNS_ATTACH_INFO pAttch = GET_VMNS_ATTACH_INFO(skb);			pAttch->type = ATT_INFO_TYPE_NONE;		if (pRD->rdesc1.byPQSTS & PQSTS_TAG) {		pAttch->type |=ATT_INFO_TYPE_TAG;				if (pRD->rdesc0.byRSR1 & RSR1_VIDHIT)			pAttch->type |=ATT_INFO_TYPE_VIDHIT;		pAttch->vlan=wTag & 0xfff;		pAttch->priority=(wTag>>12) & 0x7;		}	    if (pRD->rdesc1.byIPKT) {       pAttch->type |= ATT_INFO_TYPE_INST;	   pAttch->InstNo = pRD->rdesc1.byIPKT;	}	pAttch->protocol=skb->protocol;	skb->protocol=VMNS_FRAME_TYPE;}#endifstatic inline void rhine_rx_csum(PRX_DESC pRD, struct sk_buff* skb) {	skb->ip_summed=CHECKSUM_NONE;		if (pRD->rdesc0.byRSR0 & RSR0_FRAG) 		return;			if (pRD->rdesc1.byPQSTS & PQSTS_IPKT) {				if (pRD->rdesc1.byPQSTS & PQSTS_IPOK) {			if ((pRD->rdesc1.byPQSTS & PQSTS_TCPKT) 				||(pRD->rdesc1.byPQSTS & PQSTS_UDPKT)) {				if (!(pRD->rdesc1.byPQSTS & PQSTS_TUOK)) {					return;				}			}			skb->ip_summed=CHECKSUM_UNNECESSARY;		}	}}static BOOL rhine_receive_frame(PRHINE_INFO pInfo, PRX_DESC pRD) {   	PRHINE_RD_INFO pRDInfo=pRD->pInfo; 	   	struct net_device_stats* pStats=&pInfo->stats;   		struct sk_buff* skb;		U16		wTag;		if ((pRD->rdesc0.byRSR1 & (RSR1_STP|RSR1_EDP))		!=(RSR1_STP|RSR1_EDP)) {		RHINE_PRT(MSG_LEVEL_VERBOSE, 			KERN_NOTICE " %s : the received frame span multple RDs\n",			pInfo->dev->name);		pStats->rx_length_errors++;		return FALSE;	}	if ((pRD->rdesc1.byPQSTS & PQSTS_TAG) && 		(!(pInfo->flags & 			(RHINE_FLAGS_VMNS_COMMITTED|RHINE_FLAGS_TAGGING)			))) {		pStats->rx_dropped++;		return FALSE;							}		if (pRD->rdesc0.byRSR0 & (RSR0_RUNT|RSR0_LONG)) {		if (pRD->rdesc1.byPQSTS & PQSTS_TAG) {			if (pRD->rdesc0.f15Length<60) {				pStats->rx_length_errors++;				return FALSE;			}		} 		else {			pStats->rx_length_errors++;			return FALSE;					}		}							skb=pRDInfo->skb;			skb->dev=pInfo->dev;		pci_unmap_single(pInfo->pcid,pRDInfo->skb_dma,        		pInfo->rx_buf_sz, PCI_DMA_FROMDEVICE);         if (pInfo->flags & RHINE_FLAGS_IP_ALIGN) {    	int i;    	for (i = pRD->rdesc0.f15Length+4; i >= 0 ; i--)        	*(skb->data + i + 2) = *(skb->data + i);		skb->data += 2;		skb->tail += 2;		    }        //Get Tag	wTag=htons(*(PU16)((PU8)skb->data+((pRD->rdesc0.f15Length+3) & ~3)+2));			skb_put(skb,(pRD->rdesc0.f15Length-4));	skb->protocol=eth_type_trans(skb, skb->dev);		//drop frame not met IEEE 802.3	if (pInfo->flags & RHINE_FLAGS_VAL_PKT_LEN) {		if ((skb->protocol==ETH_P_802_3) && 			((skb->len-14)!=skb->mac.ethernet->h_proto)) {			pStats->rx_length_errors++;						return FALSE;		}	}		skb->ip_summed=CHECKSUM_NONE;			if (pInfo->flags & RHINE_FLAGS_RX_CSUM) 		rhine_rx_csum(pRD,skb);#ifdef VMNS	if (pInfo->flags & RHINE_FLAGS_VMNS_COMMITTED)		rhine_attach_vmns_info(pRD, skb, wTag);#endif		if (pRD->rdesc0.byRSR0 & RSR0_FRAG) 		skb->ip_summed=CHECKSUM_NONE;			pStats->rx_bytes+=skb->len;	pStats->rx_packets++;	netif_rx(skb);		return TRUE;}static BOOL rhine_alloc_rx_buf(PRHINE_INFO pInfo, PRX_DESC pRD) {	PRHINE_RD_INFO pRDInfo=pRD->pInfo;			pRDInfo->skb=dev_alloc_skb(pInfo->rx_buf_sz);	if (pRDInfo->skb==NULL)		return FALSE;		ASSERT(pRDInfo->skb);		pRDInfo->skb->dev=pInfo->dev;	pRDInfo->skb_dma=		pci_map_single(pInfo->pcid, pRDInfo->skb->tail, pInfo->rx_buf_sz, 			PCI_DMA_FROMDEVICE);		*((PU32) &(pRD->rdesc0)) = 0;		pRD->rdesc1.f15BufLen=cpu_to_le32(pInfo->rx_buf_sz);	pRD->rdesc0.f1Owner=OWNED_BY_NIC;	pRD->buff_addr=cpu_to_le32(pRDInfo->skb_dma);		return TRUE;	}//// Re-transmited the frame//static void rhine_tx_srv_resend(PRHINE_INFO pInfo, PTX_DESC pTD, int iQNo) {	PMAC_REGS	pMacRegs=pInfo->pMacRegs;				WAIT_MAC_TX_OFF(pMacRegs);			pTD->tdesc0.f1Owner=OWNED_BY_NIC;		writel(cpu_to_le32(pTD->pInfo->curr_desc),		&pMacRegs->adwCurrTxDescAddr[iQNo]);			BYTE_REG_BITS_ON(CR0_TXON,&pMacRegs->byCR0);			    if( pInfo->flags & RHINE_FLAGS_TAGGING)	     BYTE_REG_BITS_ON(1 << (7-iQNo), &pMacRegs->byTXQWAK);	     	BYTE_REG_BITS_ON(CR1_TDMD1,&pMacRegs->byCR1);	}////  Drop the frame//static void rhine_tx_srv_drop(PRHINE_INFO pInfo, PTX_DESC pTD, int iQNo) {	PMAC_REGS	pMacRegs=pInfo->pMacRegs;			WAIT_MAC_TX_OFF(pMacRegs);		pTD=pTD->next;		writel(cpu_to_le32(pTD->pInfo->curr_desc),		&pMacRegs->adwCurrTxDescAddr[iQNo]);				BYTE_REG_BITS_ON(CR0_TXON,&pMacRegs->byCR0);			    if( pInfo->flags & RHINE_FLAGS_TAGGING)	     BYTE_REG_BITS_ON(1 << (7-iQNo), &pMacRegs->byTXQWAK);	     	BYTE_REG_BITS_ON(CR1_TDMD1,&pMacRegs->byCR1);	}//// Drop all frame on the TX Queue//static void rhine_tx_srv_drop_all(PRHINE_INFO pInfo) {	PMAC_REGS	pMacRegs=pInfo->pMacRegs;		PTX_DESC	pTD;			int			iQNo;	struct net_device_stats* pStats=&pInfo->stats;		WAIT_MAC_TX_OFF(pMacRegs);				//Drop all transmited packets in the TD queue, because	//The TD write back status may be incorrect.		for (iQNo=0;iQNo<pInfo->nTxQueues;iQNo++) {		    for (pTD=pInfo->apTailTD[iQNo];pInfo->iTDUsed[iQNo]>0;	    	pTD=pTD->next) {	    		    	if (pTD->tdesc0.f1Owner==OWNED_BY_NIC) 	    		break;	    				rhine_free_tx_buf(pInfo,pTD);			    pInfo->iTDUsed[iQNo]--;		    pStats->tx_dropped++;		}			    pInfo->apTailTD[iQNo]=pTD;	    writel(cpu_to_le32(pTD->pInfo->curr_desc),	    	&(pMacRegs->adwCurrTxDescAddr[iQNo]));	    		    if (pInfo->flags & RHINE_FLAGS_TAGGING) 	    	BYTE_REG_BITS_ON(1<<(7-iQNo), &pMacRegs->byTXQWAK);	    	    		    		}		BYTE_REG_BITS_ON(CR0_TXON,&pMacRegs->byCR0);	BYTE_REG_BITS_ON(CR1_TDMD1,&pMacRegs->byCR1);}static void rhine_tx_srv(PRHINE_INFO pInfo, int status) {	PTX_DESC	pTD;		int			iQNo;	BOOL		bFull=FALSE;	struct net_device_stats* pStats=&pInfo->stats;		for (iQNo=0;iQNo<pInfo->nTxQueues;iQNo++) {		    for (pTD=pInfo->apTailTD[iQNo];pInfo->iTDUsed[iQNo]>0;	    	pTD=pTD->next) {	    					    	if (pTD->tdesc0.f1Owner==OWNED_BY_NIC) {	    		break;	    	}	    		    	//Only the status of first TD in the chain is correct			if (pTD->tdesc1.byTCR & TCR_STP) { 				if (pTD->tdesc0.byTSR1 & TSR1_TERR) {									RHINE_PRT(MSG_LEVEL_DEBUG, KERN_INFO						"%s : td error %x,%x\n",pInfo->dev->name,						pTD->tdesc0.byTSR1,pTD->tdesc0.byTSR0);																					pStats->tx_errors++;					if (pTD->tdesc0.byTSR1 & TSR1_UDF) {										if (pInfo->sOpts.tx_thresh<4) {							pInfo->sOpts.tx_thresh++;														RHINE_PRT(MSG_LEVEL_VERBOSE, KERN_INFO									"%s : transmitter fifo underrun occurred, increase fifo threshold to  %d\n",									pInfo->dev->name, pInfo->sOpts.tx_thresh);															rhine_set_tx_thresh(pInfo,pInfo->sOpts.tx_thresh);						}						rhine_tx_srv_resend(pInfo,pTD,iQNo);											pStats->tx_fifo_errors++;						break;					}													if (pTD->tdesc0.byTSR1 & TSR1_ABT) {							RHINE_PRT(MSG_LEVEL_VERBOSE, KERN_INFO							"%s : transmitter fifo abort occurred\n",pInfo->dev->name);						rhine_tx_srv_drop(pInfo,pTD,iQNo);						pStats->tx_aborted_errors++;					}									pStats->tx_dropped++;					if (pTD->tdesc0.byTSR1 & TSR1_CRS) 						pStats->tx_carrier_errors++;									if (pTD->tdesc0.byTSR1 & TSR1_OWC)						pStats->tx_window_errors++;					if (pTD->tdesc0.byTSR0 & TSR0_CDH)						pStats->tx_heartbeat_errors++;												} else {					pStats->collisions+=(pTD->tdesc0.byTSR0 & 0xF);					pStats->tx_packets++;					pStats->tx_bytes+=pTD->pInfo->skb->len;				}				rhine_free_tx_buf(pInfo,pTD);			    pInfo->iTDUsed[iQNo]--;			    }	    }	    	    pInfo->apTailTD[iQNo]=pTD;	    if (pInfo->iTDUsed[iQNo]>pInfo->sOpts.nTxDescs-4) {	    	bFull=TRUE;		    } 	        }		if (netif_queue_stopped(pInfo->dev) && (bFull==FALSE)) {		netif_wake_queue(pInfo->dev);	}		}static void rhine_print_link_status(PRHINE_INFO pInfo) {		if (pInfo->mii_status & RHINE_LINK_FAIL) {		RHINE_PRT(MSG_LEVEL_INFO, KERN_NOTICE			"%s: failed to detect cable link\n",pInfo->dev->name);	}	else {		if (pInfo->mii_status & RHINE_AUTONEG_ENABLE)			RHINE_PRT(MSG_LEVEL_INFO, 				"%s: Link autonegation",pInfo->dev->name)					else			RHINE_PRT(MSG_LEVEL_INFO, KERN_NOTICE				"%s: Link forced",pInfo->dev->name);						if (pInfo->mii_status & RHINE_SPEED_100) 			RHINE_PRT(MSG_LEVEL_INFO," speed 100M bps")		else 			RHINE_PRT(MSG_LEVEL_INFO," speed 10M bps");						if (pInfo->mii_status & RHINE_DUPLEX_FULL) 			RHINE_PRT(MSG_LEVEL_INFO, " full duplex\n")		else 			RHINE_PRT(MSG_LEVEL_INFO, " half duplex\n");				}}static void rhine_error(PRHINE_INFO pInfo, int status) {	if (status & ISR_SRCI) {		pInfo->mii_status=rhine_check_media_mode(pInfo);			rhine_print_link_status(pInfo);			if (pInfo->byRevId>=REV_ID_VT6102_A)			enable_flow_control_ability(pInfo);	#ifdef VMNS			if (pInfo->flags & RHINE_FLAGS_VMNS_COMMITTED) {	        PVMNS_DRV_PRIVATE pvmns_priv = pInfo->vmns_priv;            if ((pInfo->flags & RHINE_FLAGS_VMNS_COMMITTED) && pvmns_priv->notify) {            	if (pInfo->mii_status & RHINE_LINK_FAIL)	            	pvmns_priv->notify(pInfo->dev->name, VMNS_EVENT_LINK_FAIL);				else					pvmns_priv->notify(pInfo->dev->name, VMNS_EVENT_LINK_UP);			}		}#endif					};		if (status & ISR_TDWBRAI) {		RHINE_PRT(MSG_LEVEL_VERBOSE, KERN_INFO			"%s: Tx descriptor status write back race occurred.\n", 			pInfo->dev->name);		rhine_tx_srv_drop_all(pInfo);	}		if (status & ISR_BE) {		RHINE_PRT(MSG_LEVEL_ERR, KERN_ERR			"%s: Hardware fatal error.\n", 			pInfo->dev->name);		rhine_shutdown(pInfo);			}	if (status & ~(ISR_BE|ISR_TDWBRAI|ISR_SRCI)) {		RHINE_PRT(MSG_LEVEL_INFO, KERN_INFO			"%s: status %hx unhandled\n",			pInfo->dev->name, status);	}}static void rhine_free_tx_buf(PRHINE_INFO pInfo, PTX_DESC pDesc) {	PRHINE_TD_INFO	pTDInfo=pDesc->pInfo;	struct sk_buff* skb=pTDInfo->skb;	if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))	{	#ifdef RHINE_ZERO_COPY_SUPPORT        pci_unmap_single(pInfo->pcid,pTDInfo->skb_dma,        	pDesc->tdesc1.f15BufLen,PCI_DMA_TODEVICE);#else		pci_unmap_single(pInfo->pcid,pTDInfo->skb_dma,skb->len, 			PCI_DMA_TODEVICE);#endif				}		dev_kfree_skb_irq(skb);      	pTDInfo->skb_dma=0;	pTDInfo->skb=0;}static int  rhine_open(struct net_device *dev) {	PRHINE_INFO	pInfo=(PRHINE_INFO) dev->priv;	int i;	#ifdef VMNS		if (pInfo->flags & RHINE_FLAGS_OPENED)		return -EBUSY;#endif	i=request_irq(pInfo->pcid->irq, &rhine_intr, SA_SHIRQ, dev->name, dev);		if (i)		return i;		pInfo->rx_buf_sz=(dev->mtu <= 1504 ? PKT_BUF_SZ : dev->mtu + 32);	if (!rhine_init_rings(pInfo)) {		return -ENOMEM;	}	rhine_init_rd_ring(pInfo);		rhine_init_td_ring(pInfo);				rhine_init_registers(pInfo);				rhine_enable_int(pInfo);	netif_start_queue(dev);	pInfo->flags |=RHINE_FLAGS_OPENED;	MOD_INC_USE_COUNT;

⌨️ 快捷键说明

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