rhine_main.c

来自「联想网卡驱动 linux环境下编写 初写驱动的同志参考以下」· C语言 代码 · 共 2,364 行 · 第 1/5 页

C
2,364
字号
		if (pInfo->byRevId>REV_ID_VT6102_A && pInfo->byRevId<REV_ID_VT6105M_A0)		pInfo->IntMask|=IMR_TDWBRAI;				writel(cpu_to_le32(pInfo->rd_pool_dma),&pMacRegs->dwCurrRxDescAddr);			for (i=0;i<pInfo->nTxQueues;i++)		writel(cpu_to_le32(pInfo->td_pool_dma[i]),&(pMacRegs->adwCurrTxDescAddr[i]));	if (byRevId>=REV_ID_VT6105M_A0)		rhine_init_cam_filter(pInfo);	if (pInfo->flags & RHINE_FLAGS_FLOW_CTRL)		enable_flow_control(pInfo);		writew((CR0_DPOLL|CR0_TXON|CR0_RXON|CR0_STRT),&pMacRegs->byCR0);				mii_status=rhine_get_opt_media_mode(pInfo);		rhine_set_media_mode(pInfo,mii_status);		rhine_print_link_status(pInfo);	if (byRevId>=REV_ID_VT6102_A)		enable_flow_control_ability(pInfo);	rhine_ClearISR(pInfo->pMacRegs);}static BOOL rhine_soft_reset(PRHINE_INFO pInfo) {	PMAC_REGS	pMacRegs=pInfo->pMacRegs;	int i=0;				BYTE_REG_BITS_ON(CR1_SFRST, &pMacRegs->byCR1);	    /* VT86C100A may need long delay after reset (dlink) */    if (pInfo->chip_id == VT86C100A)		udelay(100);                                    for (i=0;i<W_MAX_TIMEOUT;i++) {		udelay(5);		if (!(readb(&pMacRegs->byCR1) & CR1_SFRST)) 			break;	}		if (i==W_MAX_TIMEOUT) {       	if (pInfo->chip_id==VT86C100A) {	       	printk(KERN_ERR "%s: reset did not complete in 10 ms.\n", 	       		pInfo->dev->name);        		return FALSE;       	}       		        writeb(MISC_CR1_FORSRST, &pMacRegs->byMISCCR1);        // delay 2ms       	mdelay(2);	}	return TRUE;	}static int rhine_found1(struct pci_dev *pcid, const struct pci_device_id *ent){	static BOOL			bFirst=TRUE;	struct net_device*	dev=NULL;	int					i;		PCHIP_INFO			pChip_info=(PCHIP_INFO) ent->driver_data;			PRHINE_INFO		pInfo;	PMAC_REGS			pMacRegs;	if (rhine_nics++>=MAX_UINTS) {		printk(KERN_NOTICE RHINE_NAME ": already found %d NICs\n", rhine_nics);		return -ENODEV;	}	dev=init_etherdev(dev,0);	if (dev==NULL) {		printk(KERN_ERR RHINE_NAME ": allocate net device failed");		return -ENODEV;	}	if (bFirst) {		printk(KERN_NOTICE "%s Ver. %s\n",RHINE_FULL_DRV_NAM, RHINE_VERSION);		printk(KERN_NOTICE "Copyright (c) 2002 VIA Technologies, Inc.\n");		printk(KERN_NOTICE "Copyright (c) 2002 D-Link Corporation.\n");		bFirst=FALSE;	}	if (!rhine_init_info(pcid,&pInfo, pChip_info)) {		return -ENOMEM;			}	pInfo->dev=dev;	rhine_create_proc_entry(pInfo);		dev->priv=pInfo;		dev->irq=pcid->irq;		if (pci_enable_device(pcid)) {		rhine_free_info(pInfo);		return -ENODEV;	}	if (rhine_get_pci_info(pInfo,pcid)==FALSE) {		printk(KERN_ERR RHINE_NAME ": Failed to find PCI device\n");			rhine_free_info(pInfo);		return -ENODEV;	}			enable_mmio(pInfo);			pMacRegs=ioremap(pInfo->memaddr & PCI_BASE_ADDRESS_MEM_MASK, pInfo->io_size);	pInfo->pMacRegs=pMacRegs;				if (check_region(pInfo->ioaddr,pInfo->io_size)) {		printk(KERN_ERR RHINE_NAME ": Failed to find PCI device\n");		pInfo->ioaddr=0;		rhine_free_info(pInfo);		return -ENODEV;	}		request_region(pInfo->ioaddr,pInfo->io_size,RHINE_NAME);			//Set back-off algorithm 	BYTE_REG_BITS_OFF((CFGD_CRADOM | CFGD_CAP | CFGD_MBA | CFGD_BAKOPT),		&pMacRegs->byCFGD);			dev->base_addr=pInfo->ioaddr;		for (i=0;i<6;i++) 		dev->dev_addr[i]=readb(&pMacRegs->abyPAR[i]);	rhine_print_info(pInfo);				rhine_get_options(&pInfo->sOpts,rhine_nics-1,dev->name);		//Mask out the options cannot be set to the chip	pInfo->sOpts.flags &= pChip_info->flags;		//Enable the chip specified capbilities	pInfo->flags=pInfo->sOpts.flags | (pChip_info->flags & 0xFF000000UL);	//	rhine_print_options(pInfo);		dev->irq=pcid->irq;		    dev->open 				= rhine_open;	dev->hard_start_xmit	= rhine_xmit; 	dev->stop				= rhine_close;	dev->get_stats			= rhine_get_stats;	dev->set_multicast_list	= rhine_set_multi;	dev->do_ioctl			= rhine_ioctl;	#ifdef	RHINE_ZERO_COPY_SUPPORT	dev->features			|= NETIF_F_SG;#endif#ifdef	RHINE_TX_CSUM_SUPPORT	if ((pInfo->byRevId>=REV_ID_VT6105M_A0)		&& (pInfo->flags & RHINE_FLAGS_TX_CSUM)) {		dev->features			|= NETIF_F_IP_CSUM;	}#endif		pci_set_drvdata(pcid,pInfo);		return 0;}static void	rhine_print_info(PRHINE_INFO pInfo){	struct net_device* dev=pInfo->dev;		printk(KERN_INFO "%s: %s\n",dev->name, get_chip_name(pInfo->chip_id));	printk(KERN_INFO "%s: MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",		dev->name,		dev->dev_addr[0],dev->dev_addr[1],dev->dev_addr[2],		dev->dev_addr[3],dev->dev_addr[4],dev->dev_addr[5]);					printk(" IO=0x%lx Mem=0x%lx ",(ULONG) pInfo->ioaddr,(ULONG) pInfo->pMacRegs);	printk(" IRQ=%d \n", pInfo->dev->irq);			}static BOOL	rhine_init_info(struct pci_dev* pcid, PRHINE_INFO* ppInfo,	PCHIP_INFO pChip_info) {	PRHINE_INFO	p;			*ppInfo=kmalloc(sizeof(RHINE_INFO),GFP_ATOMIC);		if (*ppInfo==NULL)		return FALSE;			memset(*ppInfo,0,sizeof(RHINE_INFO));		if (pRhine3_Infos==NULL) {		pRhine3_Infos=*ppInfo;			}	else {		for (p=pRhine3_Infos;p->next!=NULL;p=p->next)			do {} while (0);			p->next=*ppInfo;		(*ppInfo)->prev=p;	}	(*ppInfo)->pcid=pcid;	(*ppInfo)->chip_id=pChip_info->chip_id;	(*ppInfo)->io_size=pChip_info->io_size;	(*ppInfo)->nTxQueues=pChip_info->nTxQueue;	(*ppInfo)->multicast_limit=32;	#ifdef VMNS	(*ppInfo)->vmns_priv=kmalloc(sizeof(VMNS_DRV_PRIVATE),GFP_ATOMIC);	if ((*ppInfo)->vmns_priv==NULL)		return FALSE;	memset((*ppInfo)->vmns_priv,0,sizeof(VMNS_DRV_PRIVATE));#endif	spin_lock_init(&((*ppInfo)->lock));#ifdef CONFIG_PROC_FS	rhine_init_proc_fs(*ppInfo);#endif		return TRUE;}static BOOL	rhine_get_pci_info(PRHINE_INFO pInfo, struct pci_dev* pcid) {	U16	pci_cmd;    pci_read_config_byte(pcid, PCI_REVISION_ID, &pInfo->byRevId);    pci_read_config_word(pcid, PCI_SUBSYSTEM_ID,&pInfo->SubSystemID);    pci_read_config_word(pcid, PCI_SUBSYSTEM_VENDOR_ID, &pInfo->SubVendorID);    pci_read_config_word(pcid, PCI_COMMAND, (u16 *) & (pci_cmd));        pci_set_master(pcid);       	pInfo->ioaddr=pci_resource_start(pcid,0);        pInfo->memaddr=pci_resource_start(pcid,1);			pInfo->pcid=pcid;	if (pInfo->byRevId>=0x40) {		U8	b;		pci_read_config_byte(pcid,0x53, &b);		pci_write_config_byte(pcid,0x53,b|0x04);			}		if (pInfo->byRevId>=0x8A && 		pInfo->byRevId< 0x90) {		U8 b;		pci_read_config_byte(pcid,0x52, &b);		pci_write_config_byte(pcid,0x52,b|0x02);	}				return TRUE;                }static void	rhine_free_info(PRHINE_INFO pInfo) {	PRHINE_INFO			ptr;	struct net_device*	dev=pInfo->dev;	ASSERT(pInfo);	if (pRhine3_Infos==NULL)		return;		for (ptr=pRhine3_Infos;ptr && (ptr!=pInfo);ptr=ptr->next)			do {} while (0);		if (ptr==pInfo) {		if (ptr==pRhine3_Infos)			pRhine3_Infos=ptr->next;		else 			ptr->prev->next=ptr->next; 	}	else {		RHINE_PRT(MSG_LEVEL_ERR, KERN_ERR "vmns: info struct not found\n");		return;	}#ifdef CONFIG_PROC_FS	rhine_free_proc_fs(pInfo);	#endif	if (dev)		unregister_netdev(dev);		if (pInfo->pMacRegs)		iounmap(pInfo->pMacRegs);		if (pInfo->ioaddr)		release_region(pInfo->ioaddr,pInfo->io_size);	if (dev)				kfree(dev);		if (pInfo->pcid) {		pci_set_drvdata(pInfo->pcid,NULL);			}				#ifdef VMNS		if (pInfo->vmns_priv)		kfree(pInfo->vmns_priv);#endif			kfree(pInfo);	}static BOOL rhine_init_rings(PRHINE_INFO pInfo) {	void*	vir_pool;	int		i;	/*allocate all RD/TD rings a single pool*/			vir_pool=pci_alloc_consistent(pInfo->pcid, 				    pInfo->sOpts.nRxDescs * sizeof(RX_DESC) +				    pInfo->sOpts.nTxDescs * sizeof(TX_DESC)*pInfo->nTxQueues,				    &pInfo->pool_dma);				    	if (vir_pool==NULL)	{		printk(KERN_ERR "%s : allocate dma memory failed\n", pInfo->dev->name);		return FALSE;	}		memset(vir_pool,0, pInfo->sOpts.nRxDescs * sizeof(RX_DESC) +	    pInfo->sOpts.nTxDescs * sizeof(TX_DESC)*pInfo->nTxQueues);			pInfo->aRDRing=vir_pool;	pInfo->rd_pool_dma=pInfo->pool_dma;		pInfo->tx_bufs=pci_alloc_consistent(pInfo->pcid, 			    pInfo->sOpts.nTxDescs * PKT_BUF_SZ*pInfo->nTxQueues,			    &pInfo->tx_bufs_dma);		    		    	if (pInfo->tx_bufs==NULL) {		printk(KERN_ERR "%s: allocate dma memory failed\n", pInfo->dev->name);		pci_free_consistent(pInfo->pcid,	    	pInfo->sOpts.nRxDescs * sizeof(RX_DESC) +		    pInfo->sOpts.nTxDescs * sizeof(TX_DESC)*pInfo->nTxQueues,	   		pInfo->aRDRing, pInfo->pool_dma);		return FALSE;	}			memset(pInfo->tx_bufs,0,pInfo->sOpts.nTxDescs * PKT_BUF_SZ*pInfo->nTxQueues);	for (i=0;i<pInfo->nTxQueues;i++) {			pInfo->td_pool_dma[i]=pInfo->rd_pool_dma+				pInfo->sOpts.nRxDescs*sizeof(RX_DESC)+				pInfo->sOpts.nTxDescs*sizeof(TX_DESC)*i;						pInfo->apTDRings[i]=vir_pool+				pInfo->sOpts.nRxDescs*sizeof(RX_DESC)+				pInfo->sOpts.nTxDescs*sizeof(TX_DESC)*i;	}		return TRUE;	}static void rhine_free_rings(PRHINE_INFO pInfo) {	pci_free_consistent(pInfo->pcid,	    pInfo->sOpts.nRxDescs * sizeof(RX_DESC) +	    pInfo->sOpts.nTxDescs * sizeof(TX_DESC)*pInfo->nTxQueues,   		pInfo->aRDRing, pInfo->pool_dma);   		if (pInfo->tx_bufs)	   			pci_free_consistent(pInfo->pcid,			    pInfo->sOpts.nTxDescs * PKT_BUF_SZ*pInfo->nTxQueues,		   		pInfo->tx_bufs, pInfo->tx_bufs_dma);   		}static void rhine_init_rd_ring(PRHINE_INFO pInfo) {	int i;	dma_addr_t		curr=pInfo->rd_pool_dma;	PRX_DESC 		pDesc;		/* Init the RD ring entries */	for (i = 0; i < pInfo->sOpts.nRxDescs; i++, curr+=sizeof(RX_DESC)) {		pDesc=&(pInfo->aRDRing[i]);				pDesc->pInfo=alloc_rd_info();		ASSERT(pDesc->pInfo);			if (!rhine_alloc_rx_buf(pInfo, pDesc)) {			RHINE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc rx bufs\n",			pInfo->dev->name);		}				pDesc->next=&(pInfo->aRDRing[(i+1) % pInfo->sOpts.nRxDescs]);		pDesc->pInfo->curr_desc=cpu_to_le32(curr);		pDesc->next_desc = cpu_to_le32(curr+sizeof(RX_DESC));		}	pInfo->aRDRing[i-1].next_desc=cpu_to_le32(pInfo->rd_pool_dma);	pInfo->pCurrRD=&(pInfo->aRDRing[0]);}static void rhine_free_rd_ring(PRHINE_INFO pInfo) {		int i;	/* Init the RD ring entries */		for (i = 0; i < pInfo->sOpts.nRxDescs; i++) {		PRX_DESC 		pDesc=&(pInfo->aRDRing[i]);		PRHINE_RD_INFO	pRDInfo=pDesc->pInfo;				pci_unmap_single(pInfo->pcid,pRDInfo->skb_dma,           pInfo->rx_buf_sz, PCI_DMA_FROMDEVICE);           		dev_kfree_skb(pRDInfo->skb);				kfree(pDesc->pInfo);	}}static void rhine_init_td_ring(PRHINE_INFO pInfo) {	int i,j;	dma_addr_t	curr;	PTX_DESC 		pDesc;		/* Init the RD ring entries */	for (j=0;j<pInfo->nTxQueues;j++) {		curr=pInfo->td_pool_dma[j];				for (i = 0; i < pInfo->sOpts.nTxDescs; i++, curr+=sizeof(TX_DESC)) {			pDesc=&(pInfo->apTDRings[j][i]);			pDesc->pInfo=alloc_td_info();			ASSERT(pDesc->pInfo);									if (pInfo->flags & RHINE_FLAGS_TX_ALIGN) {				pDesc->pInfo->buf=pInfo->tx_bufs+(i+j)*PKT_BUF_SZ;				pDesc->pInfo->buf_dma=pInfo->tx_bufs_dma+(i+j)*PKT_BUF_SZ;			}				pDesc->next=&(pInfo->apTDRings[j][(i+1) % pInfo->sOpts.nTxDescs]);			pDesc->pInfo->curr_desc=cpu_to_le32(curr);			pDesc->tdesc1.f1Chain=1;			pDesc->next_desc = cpu_to_le32(curr+sizeof(TX_DESC));		}				pInfo->apTDRings[j][i-1].next_desc=cpu_to_le32(pInfo->td_pool_dma[j]);		pInfo->apTailTD[j]=pInfo->apCurrTD[j]=&(pInfo->apTDRings[j][0]);			}	}static void rhine_free_td_ring(PRHINE_INFO pInfo) {	int i, j;		for (j=0;j<pInfo->nTxQueues;j++) {		for (i = 0; i < pInfo->sOpts.nTxDescs; i++) {			PTX_DESC 		pDesc=&(pInfo->apTDRings[j][i]);			PRHINE_TD_INFO	pTDInfo=pDesc->pInfo;				if (pTDInfo->skb_dma) 				pci_unmap_single(pInfo->pcid,pTDInfo->skb_dma,        		   pTDInfo->skb->len, PCI_DMA_TODEVICE);        	   			if (pTDInfo->skb)				dev_kfree_skb(pTDInfo->skb);        	   			kfree(pDesc->pInfo);		}		}	}/*-----------------------------------------------------------------*/

⌨️ 快捷键说明

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