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

📄 r6040.c

📁 r6040驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
		while(lp->tx_free_desc < TX_DCNT) {			if (descptr->status & 0x8000) break; /* Not complte */			skb_ptr = descptr->skb_ptr;			pci_unmap_single(lp->pdev, descptr->buf, skb_ptr->len, PCI_DMA_TODEVICE);			dev_kfree_skb_irq(skb_ptr); /* Free buffer */			descptr->skb_ptr = 0;			descptr = descptr->vndescp; /* To next descriptor */			lp->tx_free_desc++;		}		lp->tx_remove_ptr = descptr;		if (lp->tx_free_desc) netif_wake_queue(dev);	} 	/* RX interrupt request */	if (status & 0x01) {		handled = 1;		descptr = lp->rx_remove_ptr;		while(lp->rx_free_desc) {			if (descptr->status & 0x8000) break; /* No Rx packet */			skb_ptr = descptr->skb_ptr;			descptr->skb_ptr = 0;			skb_ptr->dev = dev;			skb_put(skb_ptr, descptr->len - 4);			pci_unmap_single(lp->pdev, descptr->buf, MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);             		skb_ptr->protocol = eth_type_trans(skb_ptr, dev);             		netif_rx(skb_ptr);  /* Send to upper layer */			lp->stats.rx_packets++;			lp->stats.rx_bytes += descptr->len;			descptr = descptr->vndescp; /* To next descriptor */			lp->rx_free_desc--;		}		lp->rx_remove_ptr = descptr;	}	/* Allocate new RX buffer */	if (lp->rx_free_desc < RX_DCNT) rx_buf_alloc(lp,dev);	outw(R6040_INT_MASK, ioaddr + 0x40);	/* TX/RX interrupt enable */	spin_unlock_irqrestore(&lp->lock, flags);		return IRQ_RETVAL(handled);#endif	}static struct net_device_stats *r6040_get_stats(struct net_device *dev){	struct r6040_private *lp = dev->priv;	RDC_DBUG("r6040_get_stats()", 0);	return &lp->stats;}/* *     Set or clear the multicast filter for this adaptor. */static voidset_multicast_list(struct net_device *dev){	struct r6040_private *lp = dev->priv;	struct dev_mc_list *mcptr;	int ioaddr = dev->base_addr;	u16 *adrp, i;	unsigned long flags;	RDC_DBUG("set_multicast_list()", 0);	/* MAC Address */		adrp = (u16 *) dev->dev_addr;	outw(adrp[0], ioaddr + 0x68); 	outw(adrp[1], ioaddr + 0x6A); 	outw(adrp[2], ioaddr + 0x6C); #if RDC_DEBUG 	printk("MAC ADDR: %04x %04x %04x\n", adrp[0], adrp[1], adrp[2]);#endif	/* Promiscous Mode */	spin_lock_irqsave(&lp->lock, flags);	i = inw(ioaddr) & ~0x0120;		/* Clear AMCP & PROM */	if (dev->flags & IFF_PROMISC)	    {		 	i |= 0x0020;		lp->mcr0 |= 0x0020 ;	    }	if (dev->mc_count > 4) i |= 0x0020;	/* Too many multicast address */	outw(i, ioaddr);	spin_unlock_irqrestore(&lp->lock, flags);		/* Multicast Address */	if (dev->mc_count > 4)	/* Wait to do: Hash Table for multicast */		return;	/* Multicast Address 1~4 case */	for (i = 0, mcptr = dev->mc_list; (i<dev->mc_count) && (i<4); i++) {		adrp = (u16 *)mcptr->dmi_addr;		outw(adrp[0], ioaddr + 0x70 + 8*i); 		outw(adrp[1], ioaddr + 0x72 + 8*i); 		outw(adrp[2], ioaddr + 0x74 + 8*i); 		mcptr = mcptr->next;#if RDC_DEBUG 	printk("M_ADDR: %04x %04x %04x\n", adrp[0], adrp[1], adrp[2]);#endif	}	for (i = dev->mc_count; i < 4; i++) {		outw(0xffff, ioaddr + 0x68 + 8*i); 		outw(0xffff, ioaddr + 0x6A + 8*i); 		outw(0xffff, ioaddr + 0x6C + 8*i); 	}}static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info){	struct r6040_private *rp = dev->priv;	strcpy (info->driver, DRV_NAME);	strcpy (info->version, DRV_VERSION);	strcpy (info->bus_info, pci_name(rp->pdev));}static struct ethtool_ops netdev_ethtool_ops = {	.get_drvinfo		= netdev_get_drvinfo,};static intr6040_close(struct net_device *dev){	struct r6040_private *lp = dev->priv;	RDC_DBUG("r6040_close()", 0); 	/* deleted timer */ 	del_timer_sync(&lp->timer);	spin_lock_irq(&lp->lock);	netif_stop_queue(dev);	r6040_down(dev);	spin_unlock_irq(&lp->lock);	return 0;}/** */static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd){		struct r6040_private *lp = dev->priv;	struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;	int rc;	if (!netif_running(dev))	    return -EINVAL;	spin_lock_irq(&lp->lock);	rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL);	spin_unlock_irq(&lp->lock);	return rc;}/**	Stop RDC MAC and Free the allocated resource */static void r6040_down(struct net_device *dev){	struct r6040_private *lp = dev->priv;	int i;	u16 *adrp;	int ioaddr = dev->base_addr;	RDC_DBUG("r6040_down()", 0);	/* Stop MAC */	outw(0x0000, ioaddr + 0x40);	/* Mask Off Interrupt */	outw(0x0001, ioaddr + 0x04);	/* Reset RDC MAC */	i = 0;	do{}while((i++ < 2048) && (inw(ioaddr + 0x04) & 0x1));			//Restore MAC Address to MIDx	adrp = (u16 *) dev->dev_addr;	outw(adrp[0], ioaddr + 0x68); 	outw(adrp[1], ioaddr + 0x6A); 	outw(adrp[2], ioaddr + 0x6C); 		free_irq(dev->irq, dev);	/* Free RX buffer */	for (i = 0; i < RX_DCNT; i++) {		if (lp->rx_insert_ptr->skb_ptr) {			pci_unmap_single(lp->pdev, lp->rx_insert_ptr->buf, MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);			dev_kfree_skb(lp->rx_insert_ptr->skb_ptr);			lp->rx_insert_ptr->skb_ptr = 0;		}		lp->rx_insert_ptr = lp->rx_insert_ptr->vndescp;	}	/* Free TX buffer */	for (i = 0; i < TX_DCNT; i++) {		if (lp->tx_insert_ptr->skb_ptr) {			pci_unmap_single(lp->pdev, lp->tx_insert_ptr->buf, MAX_BUF_SIZE, PCI_DMA_TODEVICE);			dev_kfree_skb(lp->tx_insert_ptr->skb_ptr);			lp->rx_insert_ptr->skb_ptr = 0;		}		lp->tx_insert_ptr = lp->tx_insert_ptr->vndescp;	}	/* Free Descriptor memory */	pci_free_consistent(lp->pdev, ALLOC_DESC_SIZE, lp->desc_pool, lp->desc_dma);}#ifdef CONFIG_R6040_NAPIstatic int r6040_poll(struct net_device *dev, int *budget){	struct r6040_private *lp;	struct r6040_descriptor *descptr;	struct sk_buff *skb_ptr;	int ioaddr, status;	unsigned long flags;			ioaddr = dev->base_addr;		lp = (struct r6040_private *)dev->priv;	unsigned long rx_work = dev->quota ;	/* Disable RX interrupt */	local_irq_disable();	lp->NAPI_RX_RUNNING = 1 ;	outw(inw(ioaddr + 0x40) &  (~RX_INT)  ,ioaddr + 0x40 );	local_irq_enable();		{							descptr = lp->rx_remove_ptr;	while(lp->rx_free_desc) 	    {	    if (descptr->status & 0x8000) 	        break; /* No Rx packet */	    skb_ptr = descptr->skb_ptr;	    descptr->skb_ptr = 0;	    skb_ptr->dev = dev;	    skb_put(skb_ptr, descptr->len - 4);	    pci_unmap_single(lp->pdev, descptr->buf, MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);            skb_ptr->protocol = eth_type_trans(skb_ptr, dev);             		              netif_receive_skb(skb_ptr); /* Send to upper layer */	    lp->stats.rx_packets++;	    lp->stats.rx_bytes += descptr->len;	    descptr = descptr->vndescp; /* To next descriptor */	    lp->rx_free_desc--;	    }	lp->rx_remove_ptr = descptr;			}	/* Allocate new RX buffer */	if (lp->rx_free_desc < RX_DCNT) rx_buf_alloc(lp,dev);		local_irq_disable();		lp->NAPI_RX_RUNNING = 0 ;	/* Enable RX interrupt */	outw(inw(ioaddr + 0x40)| RX_INT  ,ioaddr + 0x40 );	netif_rx_complete(dev);		local_irq_enable();		return 0;	}#endif/* Init RDC MAC */static void r6040_up(struct net_device *dev){	struct r6040_private *lp = dev->priv;	struct r6040_descriptor *descptr;	int i;	int ioaddr = dev->base_addr;	u32 tmp_addr;	dma_addr_t desc_dma, start_dma;		RDC_DBUG("r6040_up()", 0);	/* Initilize */	lp->tx_free_desc = TX_DCNT;	lp->rx_free_desc = 0;		/* Init descriptor */	memset(lp->desc_pool, 0, ALLOC_DESC_SIZE); /* Let all descriptor = 0 */	lp->tx_insert_ptr = (struct r6040_descriptor *)lp->desc_pool;	lp->tx_remove_ptr = lp->tx_insert_ptr;	lp->rx_insert_ptr = (struct r6040_descriptor *)lp->tx_insert_ptr+TX_DCNT;	lp->rx_remove_ptr = lp->rx_insert_ptr;		/* Init TX descriptor */	descptr = lp->tx_insert_ptr;	desc_dma = lp->desc_dma;	start_dma = desc_dma;	for (i = 0; i < TX_DCNT; i++) {		descptr->ndesc = cpu_to_le32(desc_dma + sizeof(struct r6040_descriptor));		descptr->vndescp = (descptr + 1);		descptr = (descptr + 1);		desc_dma += sizeof(struct r6040_descriptor);	}	(descptr - 1)->ndesc = cpu_to_le32(start_dma);	(descptr - 1)->vndescp = lp->tx_insert_ptr;	/* Init RX descriptor */	start_dma = desc_dma;	descptr = lp->rx_insert_ptr;	for (i = 0; i < RX_DCNT; i++) {		descptr->ndesc = cpu_to_le32(desc_dma + sizeof(struct r6040_descriptor));		descptr->vndescp = (descptr + 1);		descptr = (descptr + 1);		desc_dma += sizeof(struct r6040_descriptor);	}	(descptr - 1)->ndesc = cpu_to_le32(start_dma);	(descptr - 1)->vndescp = lp->rx_insert_ptr;	/* Allocate buffer for RX descriptor */	rx_buf_alloc(lp,dev);#if RDC_DEBUG descptr = lp->tx_insert_ptr;for (i = 0; i < TX_DCNT; i++) { printk("%08lx:%04x %04x %08lx %08lx %08lx %08lx\n", descptr, descptr->status, descptr->len, descptr->buf, descptr->skb_ptr, descptr->ndesc, descptr->vndescp); descptr = descptr->vndescp;}descptr = lp->rx_insert_ptr;for (i = 0; i < RX_DCNT; i++) { printk("%08lx:%04x %04x %08lx %08lx %08lx %08lx\n", descptr, descptr->status, descptr->len, descptr->buf, descptr->skb_ptr, descptr->ndesc, descptr->vndescp); descptr = descptr->vndescp;}#endif		/* TX and RX descriptor start Register */	tmp_addr = cpu_to_le32(lp->tx_insert_ptr);	tmp_addr = virt_to_bus((volatile void *)tmp_addr);	outw((u16) tmp_addr, ioaddr+0x2c);	outw(tmp_addr >> 16, ioaddr+0x30);	tmp_addr = cpu_to_le32(lp->rx_insert_ptr);	tmp_addr = virt_to_bus((volatile void *)tmp_addr);	outw((u16) tmp_addr, ioaddr+0x34);	outw(tmp_addr >> 16, ioaddr+0x38);	/* Buffer Size Register */	outw(MAX_BUF_SIZE, ioaddr+0x18);	/* PHY Mode Check */	phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP);	phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE);	if (PHY_MODE == 0x3100) 		lp->phy_mode = phy_mode_chk(dev);	else lp->phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;#ifdef CONFIG_R6040_NAPI	/* Sending 15 Tx packets ,only generate one interrupt */        outw(0x0F06, ioaddr+ 0x0C);                lp->NAPI_RX_RUNNING =0;#endif		/* MAC Bus Control Register */	outw(MBCR_DEFAULT, ioaddr+0x8);	/* MAC TX/RX Enable */	lp->mcr0 |= lp->phy_mode;	outw(lp->mcr0, ioaddr);	/* Interrupt Mask Register */	outw(R6040_INT_MASK, ioaddr + 0x40);}/*  A periodic timer routine	Polling PHY Chip Link Status*/static void r6040_timer(unsigned long data){ 	struct net_device *dev=(struct net_device *)data;	struct r6040_private *lp = dev->priv;	u16 ioaddr = dev->base_addr, phy_mode;  	RDC_DBUG("r6040_timer()", 0);	/* Polling PHY Chip Status */	if (PHY_MODE == 0x3100) 		phy_mode = phy_mode_chk(dev);	else phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;	if (phy_mode != lp->phy_mode) {		lp->phy_mode = phy_mode;		lp->mcr0 = (lp->mcr0 & 0x7fff) | phy_mode;		outw(lp->mcr0, ioaddr);		printk("<RDC> Link Change %x \n", inw(ioaddr));	}	/* Debug *///	printk("<RDC> Timer: CR0 %x CR40 %x CR3C %x\n", inw(ioaddr), inw(ioaddr+0x40), inw(ioaddr+0x3c)); 	/* Timer active again */ 	lp->timer.expires = TIMER_WUT; 	add_timer(&lp->timer);}/* Allocate skb buffer for rx descriptor */static void rx_buf_alloc(struct r6040_private *lp,struct net_device *dev){	struct r6040_descriptor *descptr;	int ioaddr = dev->base_addr ;	RDC_DBUG("rx_buf_alloc()", 0);	descptr = lp->rx_insert_ptr;	while(lp->rx_free_desc < RX_DCNT){		descptr->skb_ptr = dev_alloc_skb(MAX_BUF_SIZE);		if (!descptr->skb_ptr) break;		descptr->buf = cpu_to_le32(pci_map_single(lp->pdev, descptr->skb_ptr->tail, MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));		descptr->status = 0x8000;		descptr = descptr->vndescp;		lp->rx_free_desc++;		outw(lp->mcr0 | 0x0002, ioaddr);	//Trigger Rx DMA	}	lp->rx_insert_ptr = descptr;}/* Status of PHY CHIP */static int phy_mode_chk(struct net_device *dev){	struct r6040_private *lp = dev->priv;	int ioaddr = dev->base_addr, phy_dat;	RDC_DBUG("phy_mode_chk()", 0);	/* PHY Link Status Check */	phy_dat = phy_read(ioaddr, lp->phy_addr, 1);	if (!(phy_dat & 0x4)) return 0x8000;	/* Link Failed, full duplex */	/* PHY Chip Auto-Negotiation Status */	phy_dat = phy_read(ioaddr, lp->phy_addr, 1);	if (phy_dat & 0x0020) {		/* Auto Negotiation Mode */		phy_dat = phy_read(ioaddr, lp->phy_addr, 5);		phy_dat &= phy_read(ioaddr, lp->phy_addr, 4);		if (phy_dat & 0x140) phy_dat = 0x8000;		else phy_dat = 0;	} else {		/* Force Mode */		phy_dat = phy_read(ioaddr, lp->phy_addr, 0);		if (phy_dat & 0x100) phy_dat = 0x8000;		else phy_dat = 0x0000;	}	return phy_dat;};/* Read a word data from PHY Chip */static int phy_read(int ioaddr, int phy_addr, int reg_idx){	int i = 0;	RDC_DBUG("phy_read()", 0);	outw(0x2000 + reg_idx + (phy_addr << 8), ioaddr + 0x20);	do{}while( (i++ < 2048) && (inw(ioaddr + 0x20) & 0x2000) );	return inw(ioaddr + 0x24);}/* Write a word data from PHY Chip */static void phy_write(int ioaddr, int phy_addr, int reg_idx, int dat){	int i = 0;	RDC_DBUG("phy_write()", 0);	outw(dat, ioaddr + 0x28);	outw(0x4000 + reg_idx + (phy_addr << 8), ioaddr + 0x20);	do{}while( (i++ < 2048) && (inw(ioaddr + 0x20) & 0x4000) );}enum {	RDC_6040 = 0};static int r6040_GetSet_MACaddress(struct net_device *dev){		struct r6040_private *lp = dev->priv;	int ioaddr = dev->base_addr ;	u16 *adrp ;		    	/* MAC operation register */	outw(0x01, ioaddr+0x04);	/* Reset MAC */	outw(2   , ioaddr+0xAC);	/* Reset internal state machine */	outw(0   , ioaddr+0xAC);	udelay(5000);		//Restore MAC Address */		adrp = (u16 *) dev->dev_addr;	outw(adrp[0], ioaddr + 0x68); 	outw(adrp[1], ioaddr + 0x6A); 	outw(adrp[2], ioaddr + 0x6C); }static struct pci_device_id r6040_pci_tbl[] = {	{0x17F3, 0x6040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RDC_6040},	//{0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RDC_6040},	{0,}			/* terminate list */};MODULE_DEVICE_TABLE(pci, r6040_pci_tbl);static struct pci_driver r6040_driver = {	.name		= "r6040",	.id_table	= r6040_pci_tbl,	.probe		= r6040_init_one,	.remove		= __devexit_p(r6040_remove_one),};static int __init r6040_init (void){	RDC_DBUG("r6040_init()", 0);	printk(version);	printed_version = 1;	return pci_module_init (&r6040_driver);}static void __exit r6040_cleanup (void){	RDC_DBUG("r6040_cleanup()", 0);	pci_unregister_driver (&r6040_driver);}module_init(r6040_init);module_exit(r6040_cleanup);/* * Local variables: *  compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c r6040.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" *  c-indent-level: 4 *  c-basic-offset: 4 *  tab-width: 4 * End: */

⌨️ 快捷键说明

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