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

📄 rhine_main.c

📁 联想网卡驱动 linux环境下编写 初写驱动的同志参考以下
💻 C
📖 第 1 页 / 共 5 页
字号:
	return 0;}static void rhine_shutdown(PRHINE_INFO pInfo) {	PMAC_REGS pMacRegs=pInfo->pMacRegs;			rhine_disable_int(pInfo);		writeb(CR0_STOP,&pMacRegs->byCR0);	SafeDisableMiiAutoPoll(pInfo);	rhine_ClearISR(pInfo->pMacRegs);	}static int  rhine_close(struct net_device *dev) {	PRHINE_INFO	pInfo=(PRHINE_INFO) dev->priv;		netif_stop_queue(dev);	rhine_shutdown(pInfo);			MOD_DEC_USE_COUNT;		free_irq(dev->irq, dev);		rhine_free_td_ring(pInfo);		rhine_free_rd_ring(pInfo);		rhine_free_rings(pInfo);		pInfo->flags &=(~RHINE_FLAGS_OPENED);	return 0;}static int  rhine_xmit(struct sk_buff *skb, struct net_device *dev) { 	PRHINE_INFO	pInfo=dev->priv;	int 			iQNo=0;	PTX_DESC		pTD,pHeadTD;	PMAC_REGS		pMacRegs=pInfo->pMacRegs;	int				flags;		spin_lock_irqsave(&pInfo->lock,flags);		pTD=pHeadTD=pInfo->apCurrTD[0];		ASSERT(pTD);	ASSERT(pTD->pInfo);	pHeadTD->tdesc1.byTCR=(TCR_IC|TCR_EDP|TCR_STP);	#ifdef RHINE_ZERO_COPY_SUPPORT	if (skb_shinfo(skb)->nr_frags>0) {		int	nfrags=skb_shinfo(skb)->nr_frags;		pTD->pInfo->skb=skb;				if ((AVAIL_TD(pInfo,iQNo)<nfrags) ||			(pInfo->flags & RHINE_FLAGS_TX_ALIGN)) {			skb_linearize(skb,GFP_ATOMIC);			memcpy(pTD->pInfo->buf,skb->data,skb->len);			pTD->pInfo->skb_dma=pTD->pInfo->buf_dma;    	   	pTD->buff_addr=cpu_to_le32(pTD->pInfo->skb_dma);       		pTD->tdesc1.f15BufLen=(skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);					}				else {        	        				int i;	        pTD->pInfo->skb_dma = 	        	pci_map_single(pInfo->pcid, skb->data,     	    		skb->len -skb->data_len, PCI_DMA_TODEVICE);	       	pTD->buff_addr=cpu_to_le32(pTD->pInfo->skb_dma);	       	pTD->tdesc1.f15BufLen=skb->len - skb->data_len;	       				for (i=0;i<nfrags;i++) {				skb_frag_t *frag = &skb_shinfo(skb)->frags[i];				void* addr = ((void *) page_address(frag->page + 							frag->page_offset));											pTD=pTD->next;				pTD->pInfo->skb_dma=					pci_map_single(pInfo->pcid,addr,frag->size,PCI_DMA_TODEVICE);		       	pTD->buff_addr=cpu_to_le32(pTD->pInfo->skb_dma);		       	pTD->tdesc1.f15BufLen=frag->size;			}						pTD->tdesc1.byTCR|=TCR_EDP;		} 			}	else#endif			if 	((pInfo->flags & RHINE_FLAGS_TX_ALIGN)      		&& ((long)skb->data & 3)) {    			memcpy(pHeadTD->pInfo->buf,skb->data,skb->len);	    pHeadTD->pInfo->skb=skb;				pHeadTD->pInfo->skb_dma=pHeadTD->pInfo->buf_dma;       	pHeadTD->buff_addr=cpu_to_le32(pHeadTD->pInfo->skb_dma);       	pHeadTD->tdesc1.f15BufLen=(skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);    }     else {     		    pHeadTD->pInfo->skb=skb;            pHeadTD->pInfo->skb_dma = pci_map_single(pInfo->pcid, skb->data, skb->len,         	PCI_DMA_TODEVICE);       	pHeadTD->buff_addr=cpu_to_le32(pHeadTD->pInfo->skb_dma);       	pHeadTD->tdesc1.f15BufLen=(skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);    }            #ifdef VMNS        if (pInfo->flags & RHINE_FLAGS_VMNS_COMMITTED) {    	PVMNS_ATTACH_INFO pAttch = GET_VMNS_ATTACH_INFO(skb);        if (pAttch->type & ATT_INFO_TYPE_TAG) {        	pHeadTD->tdesc0.f12VID=(pAttch->vlan & 0xfff);        	pHeadTD->tdesc0.f3Priority=(pAttch->priority & 0x7);        	pHeadTD->tdesc1.byTCR|=TCR_TAG;        }                                                            }    else#endif	if (pInfo->flags & RHINE_FLAGS_TAGGING) {       	pHeadTD->tdesc0.f12VID=(pInfo->sOpts.vid & 0xfff);       	pHeadTD->tdesc0.f3Priority=0;       	pHeadTD->tdesc1.byTCR|=TCR_TAG;	} 	#ifdef RHINE_TX_CSUM_SUPPORT	if ((pInfo->flags & RHINE_FLAGS_TX_CSUM) &&		(skb->ip_summed==CHECKSUM_HW)) {		struct iphdr* ip=skb->nh.iph;				if (ip->protocol==IPPROTO_TCP) 			pHeadTD->tdesc1.byTCR|=TCR_TCPCK;		else if (ip->protocol==IPPROTO_UDP)			pHeadTD->tdesc1.byTCR|=(TCR_UDPCK);		pHeadTD->tdesc1.byTCR|=TCR_IPCK;				}	#endif	wmb();	pHeadTD->tdesc0.f1Owner=OWNED_BY_NIC;	wmb();		pInfo->iTDUsed[iQNo]++;		pInfo->apCurrTD[iQNo]=pTD->next;  	    if (pInfo->iTDUsed[iQNo]>=pInfo->sOpts.nTxDescs-1)       	netif_stop_queue(dev);       		    if (pInfo->flags & RHINE_FLAGS_TAGGING) 	    BYTE_REG_BITS_ON(1 << (7-iQNo), &pMacRegs->byTXQWAK);	    	        BYTE_REG_BITS_ON(CR1_TDMD1,&(pMacRegs->byCR1));	    dev->trans_start = jiffies;    	spin_unlock_irqrestore(&pInfo->lock,flags);	return 0;}static void rhine_intr(int irq, void *dev_instance, struct pt_regs *regs) {	struct net_device* dev=dev_instance;		PRHINE_INFO	pInfo=(PRHINE_INFO) dev->priv;	U32				isr_status;	PMAC_REGS		pMacRegs=pInfo->pMacRegs;	int				flags;	int				max_count=0;	ASSERT(pMacRegs);			isr_status=rhine_ReadISR(pMacRegs,pInfo->byRevId);		if 	(isr_status==0) {		return;	}		rhine_disable_int(pInfo);		spin_lock_irqsave(&pInfo->lock,flags);		while (isr_status!=0) {			rhine_WriteISR(isr_status,pMacRegs,pInfo->byRevId);					if (isr_status & (ISR_SRCI|ISR_TDWBRAI|ISR_BE))			rhine_error(pInfo, isr_status);				if (isr_status & (ISR_RXE|ISR_PRX))			rhine_rx_srv(pInfo, isr_status);									if (isr_status & (ISR_TXE|ISR_PTX))			rhine_tx_srv(pInfo, isr_status);			if (max_count++>10)			break;															isr_status=rhine_ReadISR(pMacRegs,pInfo->byRevId);	}			spin_unlock_irqrestore(&pInfo->lock,flags);			rhine_enable_int(pInfo);	}void rhine_get_cam_mask(PRHINE_INFO pInfo, PU32 pMask, 	RHINE_CAM_TYPE cam_type) {	PMAC_REGS	pMacRegs=pInfo->pMacRegs;	    // enable CAMEN    if (cam_type==RHINE_VLAN_ID_CAM)	    writeb(CAMC_CAMEN | CAMC_VCAMSL, &pMacRegs->byCAMCR);	else		writeb(CAMC_CAMEN,&pMacRegs->byCAMCR);	wmb();    // read mask           *pMask = readl(&pMacRegs->dwCAMMASK);        // disable CAMEN    writeb(0, &pMacRegs->byCAMCR);    }void rhine_set_cam_mask(PRHINE_INFO pInfo, U32 mask, 	RHINE_CAM_TYPE cam_type) {	PMAC_REGS	pMacRegs=pInfo->pMacRegs;    if (cam_type==RHINE_VLAN_ID_CAM)	    writeb(CAMC_CAMEN | CAMC_VCAMSL, &pMacRegs->byCAMCR);	else		writeb(CAMC_CAMEN,&pMacRegs->byCAMCR);	wmb();    // write mask           writel(mask, &pMacRegs->dwCAMMASK);	        // disable CAMEN    writeb(0, &pMacRegs->byCAMCR);	}void rhine_set_cam(PRHINE_INFO pInfo, int idx, PU8 addr,	RHINE_CAM_TYPE cam_type) {	PMAC_REGS	pMacRegs=pInfo->pMacRegs;	int i;	    if (cam_type==RHINE_VLAN_ID_CAM)	    writeb(CAMC_CAMEN | CAMC_VCAMSL, &pMacRegs->byCAMCR);	else		writeb(CAMC_CAMEN,&pMacRegs->byCAMCR);			wmb();		writeb((U8)(idx & 0x1F), &pMacRegs->byCAMADD);		    if (cam_type==RHINE_VLAN_ID_CAM) {	    writeb(*addr, &pMacRegs->abyMAR[6]);	    writeb(*(addr+1), &pMacRegs->abyMAR[7]);	    	}	else		for (i=0;i<6;i++, addr++) 			writeb(*addr,&(pMacRegs->abyMAR[i]));	udelay(10);				wmb();				writeb(CAMC_CAMWR|CAMC_CAMEN,&pMacRegs->byCAMCR);					udelay(10);			writeb(0, &pMacRegs->byCAMCR);		}void rhine_get_cam(PRHINE_INFO pInfo, int idx, PU8 addr,	RHINE_CAM_TYPE cam_type) {	PMAC_REGS	pMacRegs=pInfo->pMacRegs;	int i;	    if (cam_type==RHINE_VLAN_ID_CAM)	    writeb(CAMC_CAMEN | CAMC_VCAMSL, &pMacRegs->byCAMCR);	else		writeb(CAMC_CAMEN,&pMacRegs->byCAMCR);			wmb();		writeb((U8)(idx & 0x1F), &pMacRegs->byCAMADD);		wmb();		writeb(CAMC_CAMRD|CAMC_CAMEN,&pMacRegs->byCAMCR);		wmb();	udelay(10);	    if (cam_type==RHINE_VLAN_ID_CAM)	    *((PU16) addr)=readw(&(pMacRegs->abyMAR[6]));	else		for (i=0;i<6;i++, addr++) 			*((PU8)addr)=readb(&(pMacRegs->abyMAR[i]));					writeb(0, &pMacRegs->byCAMCR);		}static unsigned const ethernet_polynomial = 0x04c11db7U;static inline u32 ether_crc(int length, unsigned char *data){	int crc = -1;    	while(--length >= 0) {		unsigned char current_octet = *data++;		int bit;		for (bit = 0; bit < 8; bit++, current_octet >>= 1) {			crc = (crc << 1) ^				((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);    	}	}	return crc;}                                                                            static void rhine_set_multi(struct net_device *dev) {	PRHINE_INFO			pInfo		=	(PRHINE_INFO) dev->priv;	PMAC_REGS			pMacRegs	=	pInfo->pMacRegs;	u32 				mc_filter[2];	u8 					rx_mode;	int					i;				struct dev_mc_list	*mclist; 		if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */		/* Unconditionally log net taps. */		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);		rx_mode = (RCR_AM|RCR_AB|RCR_PROM);			} 	else if ((dev->mc_count > pInfo->multicast_limit)		||  (dev->flags & IFF_ALLMULTI)) {		writel(0xffffffff, &pMacRegs->abyMAR[0]);		writel(0xffffffff, &pMacRegs->abyMAR[4]);		rx_mode = (RCR_AM|RCR_AB);	} 	else if (pInfo->flags & RHINE_FLAGS_HAVE_CAM) {		U32	mask=0;		int offset=MCAM_SIZE-pInfo->multicast_limit;		rhine_get_cam_mask(pInfo,&mask,RHINE_MULTICAST_CAM);		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;			i++, mclist = mclist->next) {					 	rhine_set_cam(pInfo,i+offset,mclist->dmi_addr,RHINE_MULTICAST_CAM);	 		mask|=1<<(offset+i);		}		rhine_set_cam_mask(pInfo,mask,RHINE_MULTICAST_CAM);		rx_mode=(RCR_AM|RCR_AB);	}	else {		memset(mc_filter, 0, sizeof(mc_filter));		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;			 i++, mclist = mclist->next) {			int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;			mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31));		}		writel(mc_filter[0], &pMacRegs->abyMAR[0]);		writel(mc_filter[1], &pMacRegs->abyMAR[4]);		rx_mode = (RCR_AM|RCR_AB);	}		writeb((pInfo->sOpts.rx_thresh<<5) | rx_mode, &pMacRegs->byRCR);	}static struct net_device_stats *rhine_get_stats(struct net_device *dev) {	PRHINE_INFO	pInfo=(PRHINE_INFO) dev->priv;		return &pInfo->stats;}static int	rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {    switch(cmd) {    #ifdef VMNS    case VMNS_DRV_SIOC: {		PVMNS_DRV_SIOC_HEADER   pParams = (PVMNS_DRV_SIOC_HEADER) rq->ifr_data;		if (!capable(CAP_NET_ADMIN))			return -EPERM;		if (vmns_process_ioctl(dev, pParams) == 0)			return 0;		}		return -EAGAIN;                                                            	#endif#ifdef RHINE_ETHTOOL_IOCTL_SUPPORT	case SIOCETHTOOL:				return rhine_ethtool_ioctl(dev, rq); 		break;#endif#ifdef RHINE_MII_IOCTL_SUPPORT	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */	case SIOCGMIIREG:		/* Read MII PHY register. */	case SIOCSMIIREG:		/* Write to MII PHY register. */		return rhine_mii_ioctl(dev, rq, cmd);		break;#endif	    default:        return -EOPNOTSUPP;    }	return 0;}/*------------------------------------------------------------------*/MODULE_DEVICE_TABLE(pci, rhine_id_table);static struct pci_driver rhine_driver = {        name:		RHINE_NAME,        id_table:	rhine_id_table,        probe:		rhine_found1,        remove:		rhine_remove1,		suspend:	NULL,        resume:		NULL}; static int __init rhine_init_module(void){    return pci_module_init(&rhine_driver);}static void __exit rhine_cleanup_module(void){    pci_unregister_driver(&rhine_driver);} module_init(rhine_init_module);module_exit(rhine_cleanup_module);/************************************************************************* MII access , media link mode setting functions************************************************************************/static void SafeDisableMiiAutoPoll (PRHINE_INFO pInfo){    WORD    	ww;	PMAC_REGS	pMacRegs=pInfo->pMacRegs;    // turn off MAUTO    writeb(0,&pMacRegs->byMIICR);    // for VT86C100A only    if (pInfo->byRevId <= REV_ID_VT86C100A_E) {        // turn off MSRCEN        // NOTE.... address of MII should be 0x01,        //          otherwise SRCI will invoked        writeb(1,&pMacRegs->byMIIAD);                mdelay(1);        // turn on MAUTO        writeb(MIICR_MAUTO,&pMacRegs->byMIICR);                // W_MAX_TIMEOUT is the timeout period        for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {        	udelay(5);        	if (readb(&pMacRegs->byMIIAD) & MIIAD_MDONE)        		break;        }                // as soon as MDONE is on,         // this is the right time to turn off MAUTO        writeb(0,&pMacRegs->byMIICR);    }    else {        // as soon as MIDLE is on, MAUTO is really stoped        for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {        	udelay(5);        	if (BYTE_REG_BITS_IS_ON(MIIAD_MIDLE, &pMacRegs->byMIIAD))        		break;        }    }}static void  EnableMiiAutoPoll(PMAC_REGS pMacRegs) {	int ii;		writeb(0,&(pMacRegs->byMIICR));	writeb(MIIAD_MSRCEN|0x01,&pMacRegs->byMIIAD);		writeb(MIICR_MAUTO,&pMacRegs->byMIICR);			for (ii=0;ii<W_MAX_TIMEOUT; ii++)		if (BYTE_REG_BITS_IS_ON(MIIAD_MDONE, &pMacRegs->byMIIAD))			break;	BYTE_REG_BITS_ON(MIIAD_MSRCEN,&pMacRegs->byMIIAD);}

⌨️ 快捷键说明

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