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

📄 ether00.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	dev->addr_len=6;	writew(0,ETHER_ARC_ADR(dev->base_addr));	writel((dev->dev_addr[0]<<24) |		(dev->dev_addr[1]<<16) |		(dev->dev_addr[2]<<8) |		dev->dev_addr[3],		ETHER_ARC_DATA(dev->base_addr));	writew(4,ETHER_ARC_ADR(dev->base_addr));	tmp=readl(ETHER_ARC_DATA(dev->base_addr));	tmp&=0xffff;	tmp|=(dev->dev_addr[4]<<24) | (dev->dev_addr[5]<<16);	writel(tmp, ETHER_ARC_DATA(dev->base_addr));	/* Enable this entry in the ARC */	writel(1,ETHER_ARC_ENA(dev->base_addr));	return;}static void ether00_reset(struct net_device *dev){	/* reset the controller */	writew(ETHER_MAC_CTL_RESET_MSK,ETHER_MAC_CTL(dev->base_addr));	/*	 * Make sure we're not going to send anything	 */	writew(ETHER_TX_CTL_TXHALT_MSK,ETHER_TX_CTL(dev->base_addr));	/*	 * Make sure we're not going to receive anything	 */	writew(ETHER_RX_CTL_RXHALT_MSK,ETHER_RX_CTL(dev->base_addr));	/*	 * Disable Interrupts for now, and set the burst size to 8 bytes	 */	writel(ETHER_DMA_CTL_INTMASK_MSK |	       ((8 << ETHER_DMA_CTL_DMBURST_OFST) & ETHER_DMA_CTL_DMBURST_MSK)	       |(2<<ETHER_DMA_CTL_RXALIGN_OFST),	       ETHER_DMA_CTL(dev->base_addr));	/*	 * Set TxThrsh - start transmitting a packet after 1514	 * bytes or when a packet is complete, whichever comes first	 */	 writew(1514,ETHER_TXTHRSH(dev->base_addr));	/*	 * Set TxPollCtr.  Each cycle is	 * 61.44 microseconds with a 33 MHz bus	 */	 writew(1,ETHER_TXPOLLCTR(dev->base_addr));	/*	 * Set Rx_Ctl - Turn off reception and let RxData turn it	 * on later	 */	 writew(ETHER_RX_CTL_RXHALT_MSK,ETHER_RX_CTL(dev->base_addr));}static void ether00_set_multicast(struct net_device* dev){	int count=dev->mc_count;	/* Set promiscuous mode if it's asked for. */	if (dev->flags&IFF_PROMISC){		writew( ETHER_ARC_CTL_COMPEN_MSK |			ETHER_ARC_CTL_BROADACC_MSK |			ETHER_ARC_CTL_GROUPACC_MSK |			ETHER_ARC_CTL_STATIONACC_MSK,			ETHER_ARC_CTL(dev->base_addr));		return;	}	/*	 * Get all multicast packets if required, or if there are too	 * many addresses to fit in hardware	 */	if (dev->flags & IFF_ALLMULTI){		writew( ETHER_ARC_CTL_COMPEN_MSK |			ETHER_ARC_CTL_GROUPACC_MSK |			ETHER_ARC_CTL_BROADACC_MSK,			ETHER_ARC_CTL(dev->base_addr));		return;	}	if (dev->mc_count > (ETHER_ARC_SIZE - 1)){		printk(KERN_WARNING "Too many multicast addresses for hardware to filter - receiving all multicast packets\n");		writew( ETHER_ARC_CTL_COMPEN_MSK |			ETHER_ARC_CTL_GROUPACC_MSK |			ETHER_ARC_CTL_BROADACC_MSK,			ETHER_ARC_CTL(dev->base_addr));		return;	}	if(dev->mc_count){		struct dev_mc_list *mc_list_ent=dev->mc_list;		unsigned int temp,i;		DEBUG(printk("mc_count=%d mc_list=%#x\n",dev-> mc_count, dev->mc_list));		DEBUG(printk("mc addr=%02#x%02x%02x%02x%02x%02x\n",			     mc_list_ent->dmi_addr[5],			     mc_list_ent->dmi_addr[4],			     mc_list_ent->dmi_addr[3],			     mc_list_ent->dmi_addr[2],			     mc_list_ent->dmi_addr[1],			     mc_list_ent->dmi_addr[0]);)		/*		 * The first 6 bytes are the MAC address, so		 * don't change them!		 */		writew(4,ETHER_ARC_ADR(dev->base_addr));		temp=readl(ETHER_ARC_DATA(dev->base_addr));		temp&=0xffff0000;		/* Disable the current multicast stuff */		writel(1,ETHER_ARC_ENA(dev->base_addr));		for(;;){			temp|=mc_list_ent->dmi_addr[1] |				mc_list_ent->dmi_addr[0]<<8;			writel(temp,ETHER_ARC_DATA(dev->base_addr));			i=readl(ETHER_ARC_ADR(dev->base_addr));			writew(i+4,ETHER_ARC_ADR(dev->base_addr));			temp=mc_list_ent->dmi_addr[5]|				mc_list_ent->dmi_addr[4]<<8 |				mc_list_ent->dmi_addr[3]<<16 |				mc_list_ent->dmi_addr[2]<<24;			writel(temp,ETHER_ARC_DATA(dev->base_addr));			count--;			if(!mc_list_ent->next || !count){				break;			}			DEBUG(printk("mc_list_next=%#x\n",mc_list_ent->next);)			mc_list_ent=mc_list_ent->next;			i=readl(ETHER_ARC_ADR(dev->base_addr));			writel(i+4,ETHER_ARC_ADR(dev->base_addr));			temp=mc_list_ent->dmi_addr[3]|				mc_list_ent->dmi_addr[2]<<8 |				mc_list_ent->dmi_addr[1]<<16 |				mc_list_ent->dmi_addr[0]<<24;			writel(temp,ETHER_ARC_DATA(dev->base_addr));			i=readl(ETHER_ARC_ADR(dev->base_addr));			writel(i+4,ETHER_ARC_ADR(dev->base_addr));			temp=mc_list_ent->dmi_addr[4]<<16 |				mc_list_ent->dmi_addr[5]<<24;			writel(temp,ETHER_ARC_DATA(dev->base_addr));			count--;			if(!mc_list_ent->next || !count){				break;			}			mc_list_ent=mc_list_ent->next;		}		if(count)			printk(KERN_WARNING "Multicast list size error\n");		writew( ETHER_ARC_CTL_BROADACC_MSK|			ETHER_ARC_CTL_COMPEN_MSK,			ETHER_ARC_CTL(dev->base_addr));	}	/* enable the active ARC enties */	writew((1<<(count+2))-1,ETHER_ARC_ENA(dev->base_addr));}static int ether00_open(struct net_device* dev){	int result,tmp;	struct net_priv* priv;	if (!is_valid_ether_addr(dev->dev_addr))		return -EINVAL;	/* Install interrupt handlers */	result=request_irq(dev->irq,ether00_int,0,"ether00",dev);	if(result)		goto open_err1;	result=request_irq(2,ether00_phy_int,0,"ether00_phy",dev);	if(result)		goto open_err2;	ether00_reset(dev);	result=ether00_mem_init(dev);	if(result)		goto open_err3;	ether00_setup_ethernet_address(dev);	ether00_set_multicast(dev);	result=ether00_write_phy(dev,PHY_CONTROL, PHY_CONTROL_ANEGEN_MSK | PHY_CONTROL_RANEG_MSK);	if(result)		goto open_err4;	result=ether00_write_phy(dev,PHY_IRQ_CONTROL, PHY_IRQ_CONTROL_LS_CHG_IE_MSK |				 PHY_IRQ_CONTROL_ANEG_COMP_IE_MSK);	if(result)		goto open_err4;	/* Start the device enable interrupts */	writew(ETHER_RX_CTL_RXEN_MSK//	       | ETHER_RX_CTL_STRIPCRC_MSK	       | ETHER_RX_CTL_ENGOOD_MSK	       | ETHER_RX_CTL_ENRXPAR_MSK| ETHER_RX_CTL_ENLONGERR_MSK	       | ETHER_RX_CTL_ENOVER_MSK| ETHER_RX_CTL_ENCRCERR_MSK,	       ETHER_RX_CTL(dev->base_addr));	writew(ETHER_TX_CTL_TXEN_MSK|	       ETHER_TX_CTL_ENEXDEFER_MSK|	       ETHER_TX_CTL_ENLCARR_MSK|	       ETHER_TX_CTL_ENEXCOLL_MSK|	       ETHER_TX_CTL_ENLATECOLL_MSK|	       ETHER_TX_CTL_ENTXPAR_MSK|	       ETHER_TX_CTL_ENCOMP_MSK,	       ETHER_TX_CTL(dev->base_addr));	tmp=readl(ETHER_DMA_CTL(dev->base_addr));	writel(tmp&~ETHER_DMA_CTL_INTMASK_MSK,ETHER_DMA_CTL(dev->base_addr));	return 0; open_err4:	ether00_reset(dev); open_err3:	free_irq(2,dev); open_err2:	free_irq(dev->irq,dev); open_err1:	return result;}static int ether00_tx(struct sk_buff* skb, struct net_device* dev){	struct net_priv *priv=dev->priv;	struct tx_fda_ent *fda_ptr;	int i;	/*	 *	Find an empty slot in which to stick the frame	 */	fda_ptr=(struct tx_fda_ent*)__dma_va(readl(ETHER_TXFRMPTR(dev->base_addr)));	i=0;	while(i<TX_NUM_FDESC){		if (fda_ptr->fd.FDStat||(fda_ptr->fd.FDCtl & FDCTL_COWNSFD_MSK)){			fda_ptr =(struct tx_fda_ent*) __dma_va((struct tx_fda_ent*)fda_ptr->fd.FDNext);		}		else {			break;		}		i++;	}	/* Write the skb data from the cache*/	consistent_sync(skb->data,skb->len,PCI_DMA_TODEVICE);	fda_ptr->bd.BuffData=(char*)__pa(skb->data);	fda_ptr->bd.BuffLength=(unsigned short)skb->len;	/* Save the pointer to the skb for freeing later */	fda_ptr->fd.FDSystem=(unsigned int)skb;	fda_ptr->fd.FDStat=0;	/* Pass ownership of the buffers to the controller */	fda_ptr->fd.FDCtl=1;	fda_ptr->fd.FDCtl|=FDCTL_COWNSFD_MSK;	/* If the next buffer in the list is full, stop the queue */	fda_ptr=(struct tx_fda_ent*)__dma_va(fda_ptr->fd.FDNext);	if ((fda_ptr->fd.FDStat)||(fda_ptr->fd.FDCtl & FDCTL_COWNSFD_MSK)){		netif_stop_queue(dev);		priv->queue_stopped=1;	}	return 0;}static struct net_device_stats *ether00_stats(struct net_device* dev){	struct net_priv *priv=dev->priv;	return &priv->stats;}static int ether00_stop(struct net_device* dev){	struct net_priv *priv=dev->priv;	int tmp;	/* Stop/disable the device. */	tmp=readw(ETHER_RX_CTL(dev->base_addr));	tmp&=~(ETHER_RX_CTL_RXEN_MSK | ETHER_RX_CTL_ENGOOD_MSK);	tmp|=ETHER_RX_CTL_RXHALT_MSK;	writew(tmp,ETHER_RX_CTL(dev->base_addr));	tmp=readl(ETHER_TX_CTL(dev->base_addr));	tmp&=~ETHER_TX_CTL_TXEN_MSK;	tmp|=ETHER_TX_CTL_TXHALT_MSK;	writel(tmp,ETHER_TX_CTL(dev->base_addr));	/* Free up system resources */	free_irq(dev->irq,dev);	free_irq(2,dev);	iounmap(priv->dma_data);	return 0;}static void ether00_get_ethernet_address(struct net_device* dev){	struct mtd_info *mymtd=NULL;	int i;	size_t retlen;	/*	 * For the Epxa10 dev board (camelot), the ethernet MAC	 * address is of the form  00:aa:aa:00:xx:xx where	 * 00:aa:aa is the Altera vendor ID and xx:xx is the	 * last 2 bytes of the board serial number, as programmed	 * into the OTP area of the flash device on EBI1. If this	 * isn't an expa10 dev board, or there's no mtd support to	 * read the serial number from flash then we'll force the	 * use to set their own mac address using ifconfig.	 */#ifdef CONFIG_ARCH_CAMELOT#ifdef CONFIG_MTD	/* get the mtd_info structure for the first mtd device*/	for(i=0;i<MAX_MTD_DEVICES;i++){		mymtd=get_mtd_device(NULL,i);		if(!mymtd||!strcmp(mymtd->name,"EPXA10DB flash"))			break;	}	if(!mymtd || !mymtd->read_user_prot_reg){		printk(KERN_WARNING "%s: Failed to read MAC address from flash\n",dev->name);	}else{		mymtd->read_user_prot_reg(mymtd,2,1,&retlen,&dev->dev_addr[5]);		mymtd->read_user_prot_reg(mymtd,3,1,&retlen,&dev->dev_addr[4]);		dev->dev_addr[3]=0;		dev->dev_addr[2]=vendor_id[1];		dev->dev_addr[1]=vendor_id[0];		dev->dev_addr[0]=0;	}#else	printk(KERN_WARNING "%s: MTD support required to read MAC address from EPXA10 dev board\n", dev->name);#endif#endif	if (!is_valid_ether_addr(dev->dev_addr))		printk("%s: Invalid ethernet MAC address.  Please set using "			"ifconfig\n", dev->name);}/* * Keep a mapping of dev_info addresses -> port lines to use when * removing ports dev==NULL indicates unused entry */static struct net_device* dev_list[ETH_NR];static int ether00_add_device(struct pldhs_dev_info* dev_info,void* dev_ps_data){	struct net_device *dev;	struct net_priv *priv;	void *map_addr;	int result;	int i;	i=0;	while(dev_list[i] && i < ETH_NR)		i++;	if(i==ETH_NR){		printk(KERN_WARNING "ether00: Maximum number of ports reached\n");		return 0;	}	if (!request_mem_region(dev_info->base_addr, MAC_REG_SIZE, "ether00"))		return -EBUSY;	dev = alloc_etherdev(sizeof(struct net_priv));	if(!dev) {		result = -ENOMEM;		goto out_release;	}	priv = dev->priv;	priv->tq_memupdate.routine=ether00_mem_update;	priv->tq_memupdate.data=(void*) dev;	spin_lock_init(&priv->rx_lock);	map_addr=ioremap_nocache(dev_info->base_addr,SZ_4K);	if(!map_addr){		result = -ENOMEM;		out_kfree;	}	dev->open=ether00_open;	dev->stop=ether00_stop;	dev->set_multicast_list=ether00_set_multicast;	dev->hard_start_xmit=ether00_tx;	dev->get_stats=ether00_stats;	ether00_get_ethernet_address(dev);	SET_MODULE_OWNER(dev);	dev->base_addr=(unsigned int)map_addr;	dev->irq=dev_info->irq;	dev->features=NETIF_F_DYNALLOC | NETIF_F_HW_CSUM;	result=register_netdev(dev);	if(result){		printk("Ether00: Error %i registering driver\n",result);		goto out_unmap;	}	printk("registered ether00 device at %#x\n",dev_info->base_addr);	dev_list[i]=dev;	return result; out_unmap:	iounmap(map_addr); out_kfree:	free_netdev(dev); out_release:	release_mem_region(dev_info->base_addr, MAC_REG_SIZE);	return result;}static int ether00_remove_devices(void){	int i;	for(i=0;i<ETH_NR;i++){		if(dev_list[i]){			netif_device_detach(dev_list[i]);			unregister_netdev(dev_list[i]);			iounmap((void*)dev_list[i]->base_addr);			release_mem_region(dev_list[i]->base_addr, MAC_REG_SIZE);			free_netdev(dev_list[i]);			dev_list[i]=0;		}	}	return 0;}static struct pld_hotswap_ops ether00_pldhs_ops={	.name = ETHER00_NAME,	.add_device = ether00_add_device,	.remove_devices = ether00_remove_devices,};static void __exit ether00_cleanup_module(void){	int result;	result=ether00_remove_devices();	if(result)		printk(KERN_WARNING "ether00: failed to remove all devices\n");	pldhs_unregister_driver(ETHER00_NAME);}module_exit(ether00_cleanup_module);static int __init ether00_mod_init(void){	printk("mod init\n");	return pldhs_register_driver(&ether00_pldhs_ops);}module_init(ether00_mod_init);

⌨️ 快捷键说明

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