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

📄 at91_ether.c

📁 AT91RM9200 BSP with dual ethernet port
💻 C
📖 第 1 页 / 共 2 页
字号:
{	AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;	write_phy(regs, phy_id, location, value);}#if 0/* * ethtool support. */static int at91ether_ethtool_ioctl (struct net_device *dev, void *useraddr){	struct at91_private *lp = (struct at91_private *) dev->priv;	AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;	unsigned long ethcmd;	int res = 0;	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))		return -EFAULT;	spin_lock_irq(&lp->lock);	enable_mdi(regs);	switch (ethcmd) {	case ETHTOOL_GSET: {		struct ethtool_cmd ecmd = { ETHTOOL_GSET };		res = mii_ethtool_gset(&lp->mii, &ecmd);		if (lp->phy_media == PORT_FIBRE) {		/* override media type since mii.c doesn't know */			ecmd.supported = SUPPORTED_FIBRE;			ecmd.port = PORT_FIBRE;		}		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))			res = -EFAULT;		break;	}	case ETHTOOL_SSET: {		struct ethtool_cmd ecmd;		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))			res = -EFAULT;		else			res = mii_ethtool_sset(&lp->mii, &ecmd);		break;	}	case ETHTOOL_NWAY_RST: {		res = mii_nway_restart(&lp->mii);		break;	}	case ETHTOOL_GLINK: {		struct ethtool_value edata = { ETHTOOL_GLINK };		edata.data = mii_link_ok(&lp->mii);		if (copy_to_user(useraddr, &edata, sizeof(edata)))			res = -EFAULT;		break;	}	default:		res = -EOPNOTSUPP;	}	disable_mdi(regs);	spin_unlock_irq(&lp->lock);	return res;}/* * User-space ioctl interface. */static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	switch(cmd) {	case SIOCETHTOOL:		return at91ether_ethtool_ioctl(dev, (void *) rq->ifr_data);	default:		return -EOPNOTSUPP;	}}#endif/* ................................ MAC ................................ *//* * Initialize and start the Receiver and Transmit subsystems */  static void at91ether_start(struct net_device *dev){	AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;	struct at91_private *lp = (struct at91_private *) dev->priv;	int i;	struct recv_desc_bufs *dlist, *dlist_phys;    char                    *pNewCluster;	dlist = lp->dlist;	dlist_phys = lp->dlist_phys;	for (i = 0; i < MAX_RX_DESCR; i++) {/*		dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0];*/ /*     pNewCluster = netClusterGet (dev->endObj.pNetPool,                                     dev->endObj.pNetPool->clTbl[0]);        if (pNewCluster == NULL)        {	        dev->lastError.errCode = END_ERR_NO_BUF;	        muxError(&dev->endObj, &dev->lastError);	        return ;        }        pNewCluster = END_CACHE_VIRT_TO_PHYS(pNewCluster);		dlist->descriptors[i].addr = pNewCluster;*/		dlist->descriptors[i].addr = dlist->recv_buf[i];		dlist->descriptors[i].size = 0;	}	/* Set the Wrap bit on the last descriptor */	dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP;	/* Reset buffer index */	lp->rxBuffIndex = 0;	/* Program address of descriptor list in Rx Buffer Queue register */	regs->EMAC_RBQP = (AT91_REG) dlist_phys;	/* Enable Receive and Transmit */	regs->EMAC_CTL |= (AT91C_EMAC_RE | AT91C_EMAC_TE);	intEnable(AT91C_ID_PIOC);	intEnable(dev->irq);}/* * Open the ethernet interface */static int at91ether_open(struct net_device *dev){	struct at91_private *lp = (struct at91_private *) dev->priv;	AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;        if (!is_valid_ether_addr(dev->dev_addr))        	return -EADDRNOTAVAIL;	AT91_SYS->PMC_PCER = 1 << AT91C_ID_EMAC;	/* Re-enable Peripheral clock */	regs->EMAC_CTL |= AT91C_EMAC_CSR;		/* Clear internal statistics */	/* Update the MAC address (incase user has changed it) */	update_mac_address(dev);	/* Enable PHY interrupt */	enable_phyirq(dev, regs);	/* Enable MAC interrupts */	regs->EMAC_IER = AT91C_EMAC_RCOM | AT91C_EMAC_RBNA			| AT91C_EMAC_TUND | AT91C_EMAC_RTRY | AT91C_EMAC_TCOM			| AT91C_EMAC_ROVR | AT91C_EMAC_HRESP;	/* Determine current link speed */	spin_lock_irq(&lp->lock);	enable_mdi(regs);	(void) update_linkspeed(dev, regs);	disable_mdi(regs);	spin_unlock_irq(&lp->lock);	at91ether_start(dev);/*	netif_start_queue(dev);*/	return 0;}/* * Close the interface */static int at91ether_close(struct net_device *dev){	AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;	/* Disable Receiver and Transmitter */	regs->EMAC_CTL &= ~(AT91C_EMAC_TE | AT91C_EMAC_RE);	/* Disable PHY interrupt */	disable_phyirq(dev, regs);	/* Disable MAC interrupts */	regs->EMAC_IDR = AT91C_EMAC_RCOM | AT91C_EMAC_RBNA			| AT91C_EMAC_TUND | AT91C_EMAC_RTRY | AT91C_EMAC_TCOM			| AT91C_EMAC_ROVR | AT91C_EMAC_HRESP;	/*netif_stop_queue(dev);*/	AT91_SYS->PMC_PCDR = 1 << AT91C_ID_EMAC;	/* Disable Peripheral clock */	return 0;}#if 0/* * Transmit packet. */static int at91ether_tx(struct sk_buff *skb, struct net_device *dev){	AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;	struct at91_private *lp = (struct at91_private *) dev->priv;	if (regs->EMAC_TSR & AT91C_EMAC_BNQ) {		/*netif_stop_queue(dev);*/		/* Store packet information (to free when Tx completed) */		lp->skb = skb;		lp->skb_length = skb->len;		lp->skb_physaddr = pci_map_single(NULL, skb->data, skb->len, PCI_DMA_TODEVICE);		lp->stats.tx_bytes += skb->len;		/* Set address of the data in the Transmit Address register */		regs->EMAC_TAR = lp->skb_physaddr;		/* Set length of the packet in the Transmit Control register */		regs->EMAC_TCR = skb->len;		dev->trans_start = jiffies;	} else {		printk(KERN_ERR "at91_ether.c: at91ether_tx() called, but device is busy!\n");		return 1;	/* if we return anything but zero, dev.c:1055 calls kfree_skb(skb)				on this skb, he also reports -ENETDOWN and printk's, so either				we free and return(0) or don't free and return 1 */	}	return 0;}#endif/* * Update the current statistics from the internal statistics registers. */static struct net_device_stats *at91ether_stats(struct net_device *dev){	struct at91_private *lp = (struct at91_private *) dev->priv;	AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;	int ale, lenerr, seqe, lcol, ecol;	/*if (netif_running(dev)) */{		lp->stats.rx_packets += regs->EMAC_OK;			/* Good frames received */		ale = regs->EMAC_ALE;		lp->stats.rx_frame_errors += ale;			/* Alignment errors */		lenerr = regs->EMAC_ELR + regs->EMAC_USF;		lp->stats.rx_length_errors += lenerr;			/* Excessive Length or Undersize Frame error */		seqe = regs->EMAC_SEQE;		lp->stats.rx_crc_errors += seqe;			/* CRC error */		lp->stats.rx_fifo_errors += regs->EMAC_DRFC;		/* Receive buffer not available */		lp->stats.rx_errors += (ale + lenerr + seqe + regs->EMAC_CDE + regs->EMAC_RJB);		lp->stats.tx_packets += regs->EMAC_FRA;			/* Frames successfully transmitted */		lp->stats.tx_fifo_errors += regs->EMAC_TUE;		/* Transmit FIFO underruns */		lp->stats.tx_carrier_errors += regs->EMAC_CSE;		/* Carrier Sense errors */		lp->stats.tx_heartbeat_errors += regs->EMAC_SQEE;	/* Heartbeat error */		lcol = regs->EMAC_LCOL;		ecol = regs->EMAC_ECOL;		lp->stats.tx_window_errors += lcol;			/* Late collisions */		lp->stats.tx_aborted_errors += ecol;			/* 16 collisions */		lp->stats.collisions += (regs->EMAC_SCOL + regs->EMAC_MCOL + lcol + ecol);	}	return &lp->stats;}/* * Extract received frame from buffer descriptors and sent to upper layers. * (Called from interrupt context) */static void at91ether_rx(struct net_device *dev){	struct at91_private *lp = (struct at91_private *) dev->priv;	struct recv_desc_bufs *dlist;/*	unsigned char *p_recv;*//*	struct sk_buff *skb;*//*	unsigned int pktlen;*/	AT91PS_EMAC emac = (AT91PS_EMAC) dev->base_addr;	if (emac->EMAC_RSR & AT91C_EMAC_REC)		emac->EMAC_RSR |= AT91C_EMAC_REC;	if(( !dev->bPolling) && (!dev->bRxHandler))        {            dev->bRxHandler = TRUE;            netJobAdd((FUNCPTR)at91EthRxHandler, (int)dev, 0, 0, 0, 0);        } }/* * MAC interrupt handler */static void at91ether_interrupt(ETH_DRV_CTRL *dev ){	struct at91_private *lp = (struct at91_private *) dev->priv;	AT91PS_EMAC emac = (AT91PS_EMAC) dev->base_addr;	unsigned long intstatus;	/* MAC Interrupt Status register indicates what interrupts are pending.	   It is automatically cleared once read. */	intstatus = emac->EMAC_ISR;	if (intstatus & AT91C_EMAC_RCOM)		/* Receive complete */		at91ether_rx(dev);	if (intstatus & AT91C_EMAC_TCOM) {		/* Transmit complete */			/* The TCOM bit is set even if the transmission failed. */		if (intstatus & (AT91C_EMAC_TUND | AT91C_EMAC_RTRY))			lp->stats.tx_errors += 1;	        if ((!dev->bPolling) && (!dev->bTxHandler))	        {	            dev->bTxHandler = TRUE;		            netJobAdd((FUNCPTR)at91EthTxHandler, (int)dev, 0, 0, 0, 0);	        }		/*dev_kfree_skb_irq(lp->skb);*/		/*pci_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, PCI_DMA_TODEVICE);*/		/*netif_wake_queue(dev);*/	}	/* Work-around for Errata #11 */	if (intstatus & AT91C_EMAC_RBNA) {		emac->EMAC_CTL &= ~AT91C_EMAC_RE;		emac->EMAC_CTL |= AT91C_EMAC_RE;	}		if (intstatus & AT91C_EMAC_ROVR)		printk("%s: ROVR error\n", dev->name);}/* * Initialize the ethernet interface */static int at91ether_setup(struct net_device *dev, unsigned long phy_type){	AT91PS_EMAC regs;	static int already_initialized = 0;	struct at91_private *lp = &at91_mac_private;	unsigned int val;	unsigned long addr;	if (already_initialized)		return 0;/*	dev = init_etherdev(dev, sizeof(struct at91_private));*/	dev->base_addr = AT91C_VA_BASE_EMAC;	dev->irq = AT91C_ID_EMAC;	/* Install the interrupt handler */	if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev))		return -EBUSY;	memset(lp, 0, sizeof(struct at91_private));	dev->priv = lp;	/* Allocate memory for DMA Receive descriptors */	addr = (unsigned long) cacheDmaMalloc(sizeof(struct recv_desc_bufs)+0x100);	if(addr&0xFF) addr=(addr&0xffffff00)+0x100;	lp->dlist = (struct recv_desc_bufs *) addr;	lp->dlist_phys  = lp->dlist ; /* cacheDrvVirtToPhys();*/	spin_lock_init(&lp->lock);/*	ether_setup(dev);	dev->open = at91ether_open;	dev->stop = at91ether_close;	dev->hard_start_xmit = at91ether_tx;	dev->get_stats = at91ether_stats;	dev->set_multicast_list = at91ether_set_rx_mode;	dev->do_ioctl = at91ether_ioctl;	dev->set_mac_address = set_mac_address;*/	get_mac_address(dev);		/* Get ethernet address and store it in dev->dev_addr */	update_mac_address(dev);	/* Program ethernet address into MAC */	regs = (AT91PS_EMAC) dev->base_addr;	regs->EMAC_CTL = 0;#ifdef CONFIG_AT91_ETHER_RMII	regs->EMAC_CFG = AT91C_EMAC_BIG | AT91C_EMAC_RMII;#else	regs->EMAC_CFG = AT91C_EMAC_BIG;#endif	if (phy_type == MII_LXT971A_ID)		regs->EMAC_CFG |= AT91C_EMAC_CLK_HCLK_64;	/* MDIO clock = system clock/64 */	if (phy_type == MII_DM9161_ID) {		spin_lock_irq(&lp->lock);		enable_mdi(regs);		read_phy(regs, 0, MII_DSCR_REG, &val);		if ((val & (1 << 10)) == 0)			/* DSCR bit 10 is 0 -- fiber mode */			lp->phy_media = PORT_FIBRE;		disable_mdi(regs);		spin_unlock_irq(&lp->lock);	}	if (phy_type == MII_RTL8201BL_ID) 		regs->EMAC_CFG |= AT91C_EMAC_CLK_HCLK_64;	/* MDIO clock = system clock/64 */	/*	lp->mii.dev = dev;			lp->mii.mdio_read = mdio_read;	lp->mii.mdio_write = mdio_write;	*/	lp->phy_type = phy_type;	/* Type of PHY connected */	/* Determine current link speed */	spin_lock_irq(&lp->lock);	enable_mdi(regs);	(void) update_linkspeed(dev, regs);	disable_mdi(regs);	spin_unlock_irq(&lp->lock);	if (phy_type == MII_DM9161_ID)		printk(KERN_INFO "%s: Davicom 9196 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");	else if (phy_type == MII_LXT971A_ID)		printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);	if (phy_type == MII_RTL8201BL_ID)		printk(KERN_INFO "%s: Realtek 8201BL PHY\n", dev->name);	already_initialized = 1;	return 0;}/* * Detect MAC and PHY and perform initialization */static int at91ether_probe(struct net_device *dev){	AT91PS_EMAC regs = (AT91PS_EMAC) AT91C_VA_BASE_EMAC;	unsigned int phyid1, phyid2;	int detected = -1;	/* Configure the hardware - RMII vs MII mode */#ifdef CONFIG_AT91_ETHER_RMII	AT91_CfgPIO_EMAC_RMII();#else	AT91_CfgPIO_EMAC_MII();#endif	AT91_CfgPIO_EMAC_PHY();				/* Configure PHY interrupt */	AT91_SYS->PMC_PCER = 1 << AT91C_ID_EMAC;	/* Enable Peripheral clock */	/* Read the PHY ID registers */	enable_mdi(regs);	read_phy(regs, 0, MII_PHYSID1, &phyid1);	read_phy(regs, 0, MII_PHYSID2, &phyid2);	disable_mdi(regs);	/* Davicom 9161: PHY_ID1 = 0x181  PHY_ID2 = B881 */	if (((phyid1 << 16) | (phyid2 & 0xfff0)) == MII_DM9161_ID) {		detected = at91ether_setup(dev, MII_DM9161_ID);	}	/* Intel LXT971A: PHY_ID1 = 0x13  PHY_ID2 = 78E0 */	else if (((phyid1 << 16) | (phyid2 & 0xfff0)) == MII_LXT971A_ID) {		detected = at91ether_setup(dev, MII_LXT971A_ID);	}else if (((phyid1 << 16) | (phyid2 & 0xffff)) == MII_RTL8201BL_ID) {		detected = at91ether_setup(dev, MII_RTL8201BL_ID);	}	AT91_SYS->PMC_PCDR = 1 << AT91C_ID_EMAC;	/* Disable Peripheral clock */	return detected;}

⌨️ 快捷键说明

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