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

📄 sungem.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Make us not-running to avoid timers respawning */	gp->hw_running = 0;	/* Stop the link timer */	del_timer_sync(&gp->link_timer);	/* Stop the reset task */	while (gp->reset_task_pending)		schedule();		/* Actually stop the chip */	if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {		gem_stop_phy(gp);#ifdef CONFIG_ALL_PPC		/* Power down the chip */		gem_apple_powerdown(gp);#endif /* CONFIG_ALL_PPC */	} else		gem_stop(gp);}static void gem_pm_task(void *data){	struct gem *gp = (struct gem *) data;	/* We assume if we can't lock the pm_sem, then open() was	 * called again (or suspend()), and we can safely ignore	 * the PM request	 */	if (down_trylock(&gp->pm_sem))		return;	/* Driver was re-opened or already shut down */	if (gp->opened || !gp->hw_running) {		up(&gp->pm_sem);		return;	}	gem_shutdown(gp);	up(&gp->pm_sem);}static void gem_pm_timer(unsigned long data){	struct gem *gp = (struct gem *) data;	schedule_task(&gp->pm_task);}static int gem_open(struct net_device *dev){	struct gem *gp = dev->priv;	int hw_was_up = gp->hw_running;	down(&gp->pm_sem);	/* Stop the PM timer/task */	del_timer(&gp->pm_timer);	flush_scheduled_tasks();	if (!gp->hw_running) {#ifdef CONFIG_ALL_PPC		/* First, we need to bring up the chip */		if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {			gem_apple_powerup(gp);			gem_check_invariants(gp);		}#endif /* CONFIG_ALL_PPC */		/* Reset the chip */		gem_stop(gp);		gp->hw_running = 1;	}	/* We can now request the interrupt as we know it's masked	 * on the controller	 */	if (request_irq(gp->pdev->irq, gem_interrupt,			SA_SHIRQ, dev->name, (void *)dev)) {		printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name);#ifdef CONFIG_ALL_PPC		if (!hw_was_up && gp->pdev->vendor == PCI_VENDOR_ID_APPLE)			gem_apple_powerdown(gp);#endif /* CONFIG_ALL_PPC */		/* Fire the PM timer that will shut us down in about 10 seconds */		gp->pm_timer.expires = jiffies + 10*HZ;		add_timer(&gp->pm_timer);		up(&gp->pm_sem);		return -EAGAIN;	}	/* Allocate & setup ring buffers */	gem_init_rings(gp, 0);	/* Init & setup chip hardware */	gem_init_hw(gp, !hw_was_up);	gp->opened = 1;	up(&gp->pm_sem);	return 0;}static int gem_close(struct net_device *dev){	struct gem *gp = dev->priv;	/* Make sure we don't get distracted by suspend/resume */	down(&gp->pm_sem);	/* Stop traffic, mark us closed */	spin_lock_irq(&gp->lock);	gp->opened = 0;		writel(0xffffffff, gp->regs + GREG_IMASK);	netif_stop_queue(dev);	spin_unlock_irq(&gp->lock);	/* Stop chip */	gem_stop(gp);	/* Get rid of rings */	gem_clean_rings(gp);	/* Bye, the pm timer will finish the job */	free_irq(gp->pdev->irq, (void *) dev);	/* Fire the PM timer that will shut us down in about 10 seconds */	gp->pm_timer.expires = jiffies + 10*HZ;	add_timer(&gp->pm_timer);	up(&gp->pm_sem);		return 0;}#ifdef CONFIG_PMstatic int gem_suspend(struct pci_dev *pdev, u32 state){	struct net_device *dev = pci_get_drvdata(pdev);	struct gem *gp = dev->priv;	/* We hold the PM semaphore during entire driver	 * sleep time	 */	down(&gp->pm_sem);	printk(KERN_INFO "%s: suspending, WakeOnLan %s\n",	       dev->name, gp->wake_on_lan ? "enabled" : "disabled");		/* If the driver is opened, we stop the DMA */	if (gp->opened) {		/* Stop traffic, mark us closed */		netif_device_detach(dev);		spin_lock_irq(&gp->lock);		writel(0xffffffff, gp->regs + GREG_IMASK);		spin_unlock_irq(&gp->lock);		/* Stop chip */		gem_stop(gp);		/* Get rid of ring buffers */		gem_clean_rings(gp);		if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)			disable_irq(gp->pdev->irq);	}	if (gp->hw_running) {		/* Kill PM timer if any */		del_timer_sync(&gp->pm_timer);		flush_scheduled_tasks();		gem_shutdown(gp);	}	return 0;}static int gem_resume(struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata(pdev);	struct gem *gp = dev->priv;	printk(KERN_INFO "%s: resuming\n", dev->name);	if (gp->opened) {#ifdef CONFIG_ALL_PPC		/* First, we need to bring up the chip */		if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {			gem_apple_powerup(gp);			gem_check_invariants(gp);		}#endif /* CONFIG_ALL_PPC */		gem_stop(gp);		gp->hw_running = 1;		gem_init_rings(gp, 0);		gem_init_hw(gp, 1);		netif_device_attach(dev);		if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)			enable_irq(gp->pdev->irq);	}	up(&gp->pm_sem);	return 0;}#endif /* CONFIG_PM */static struct net_device_stats *gem_get_stats(struct net_device *dev){	struct gem *gp = dev->priv;	struct net_device_stats *stats = &gp->net_stats;	if (gp->hw_running) {		stats->rx_crc_errors += readl(gp->regs + MAC_FCSERR);		writel(0, gp->regs + MAC_FCSERR);		stats->rx_frame_errors += readl(gp->regs + MAC_AERR);		writel(0, gp->regs + MAC_AERR);		stats->rx_length_errors += readl(gp->regs + MAC_LERR);		writel(0, gp->regs + MAC_LERR);		stats->tx_aborted_errors += readl(gp->regs + MAC_ECOLL);		stats->collisions +=			(readl(gp->regs + MAC_ECOLL) +			 readl(gp->regs + MAC_LCOLL));		writel(0, gp->regs + MAC_ECOLL);		writel(0, gp->regs + MAC_LCOLL);	}	return &gp->net_stats;}static void gem_set_multicast(struct net_device *dev){	struct gem *gp = dev->priv;	u32 rxcfg, rxcfg_new;	int limit = 10000;		if (!gp->hw_running)		return;			netif_stop_queue(dev);	rxcfg = readl(gp->regs + MAC_RXCFG);	rxcfg_new = gem_setup_multicast(gp);		writel(rxcfg & ~MAC_RXCFG_ENAB, gp->regs + MAC_RXCFG);	while (readl(gp->regs + MAC_RXCFG) & MAC_RXCFG_ENAB) {		if (!limit--)			break;		udelay(10);	}	rxcfg &= ~(MAC_RXCFG_PROM | MAC_RXCFG_HFE);	rxcfg |= rxcfg_new;	writel(rxcfg, gp->regs + MAC_RXCFG);	/* Hrm... we may walk on the reset task here... */	netif_wake_queue(dev);}/* Eventually add support for changing the advertisement * on autoneg. */static int gem_ethtool_ioctl(struct net_device *dev, void *ep_user){	struct gem *gp = dev->priv;	u16 bmcr;	int full_duplex, speed, pause;	struct ethtool_cmd ecmd;	if (copy_from_user(&ecmd, ep_user, sizeof(ecmd)))		return -EFAULT;			switch(ecmd.cmd) {        case ETHTOOL_GDRVINFO: {		struct ethtool_drvinfo info = { cmd: ETHTOOL_GDRVINFO };		strncpy(info.driver, DRV_NAME, ETHTOOL_BUSINFO_LEN);		strncpy(info.version, DRV_VERSION, ETHTOOL_BUSINFO_LEN);		info.fw_version[0] = '\0';		strncpy(info.bus_info, gp->pdev->slot_name, ETHTOOL_BUSINFO_LEN);		info.regdump_len = 0; /*SUNGEM_NREGS;*/		if (copy_to_user(ep_user, &info, sizeof(info)))			return -EFAULT;		return 0;	}	case ETHTOOL_GSET:		ecmd.supported =			(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |			 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |			 SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);		if (gp->gigabit_capable)			ecmd.supported |=				(SUPPORTED_1000baseT_Half |				 SUPPORTED_1000baseT_Full);		/* XXX hardcoded stuff for now */		ecmd.port = PORT_MII;		ecmd.transceiver = XCVR_EXTERNAL;		ecmd.phy_address = 0; /* XXX fixed PHYAD */		/* Record PHY settings if HW is on. */		if (gp->hw_running) {			bmcr = phy_read(gp, MII_BMCR);			gem_read_mii_link_mode(gp, &full_duplex, &speed, &pause);		} else			bmcr = 0;		if (bmcr & BMCR_ANENABLE) {			ecmd.autoneg = AUTONEG_ENABLE;			ecmd.speed = speed == 10 ? SPEED_10 : (speed == 1000 ? SPEED_1000 : SPEED_100);			ecmd.duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF;		} else {			ecmd.autoneg = AUTONEG_DISABLE;			ecmd.speed =				(bmcr & BMCR_SPEED100) ?				SPEED_100 : SPEED_10;			ecmd.duplex =				(bmcr & BMCR_FULLDPLX) ?				DUPLEX_FULL : DUPLEX_HALF;		}		if (copy_to_user(ep_user, &ecmd, sizeof(ecmd)))			return -EFAULT;		return 0;	case ETHTOOL_SSET:		if (!capable(CAP_NET_ADMIN))			return -EPERM;		/* Verify the settings we care about. */		if (ecmd.autoneg != AUTONEG_ENABLE &&		    ecmd.autoneg != AUTONEG_DISABLE)			return -EINVAL;		if (ecmd.autoneg == AUTONEG_DISABLE &&		    ((ecmd.speed != SPEED_100 &&		      ecmd.speed != SPEED_10) ||		     (ecmd.duplex != DUPLEX_HALF &&		      ecmd.duplex != DUPLEX_FULL)))			return -EINVAL;		/* Apply settings and restart link process */		if (gp->hw_running)			del_timer(&gp->link_timer);		gem_begin_auto_negotiation(gp, &ecmd);		return 0;	case ETHTOOL_NWAY_RST:		if ((gp->link_cntl & BMCR_ANENABLE) == 0)			return -EINVAL;		if (gp->hw_running)			del_timer(&gp->link_timer);		gem_begin_auto_negotiation(gp, NULL);		return 0;	case ETHTOOL_GWOL:	case ETHTOOL_SWOL:		break; /* todo */	/* get link status */	case ETHTOOL_GLINK: {		struct ethtool_value edata = { cmd: ETHTOOL_GLINK };		edata.data = (gp->lstate == link_up);		if (copy_to_user(ep_user, &edata, sizeof(edata)))			return -EFAULT;		return 0;	}	/* get message-level */	case ETHTOOL_GMSGLVL: {		struct ethtool_value edata = { cmd: ETHTOOL_GMSGLVL };		edata.data = gp->msg_enable;		if (copy_to_user(ep_user, &edata, sizeof(edata)))			return -EFAULT;		return 0;	}	/* set message-level */	case ETHTOOL_SMSGLVL: {		struct ethtool_value edata;		if (copy_from_user(&edata, ep_user, sizeof(edata)))			return -EFAULT;		gp->msg_enable = edata.data;		return 0;	}#if 0	case ETHTOOL_GREGS: {		struct ethtool_regs regs;		u32 *regbuf;		int r = 0;		if (copy_from_user(&regs, useraddr, sizeof(regs)))			return -EFAULT;				if (regs.len > SUNGEM_NREGS) {			regs.len = SUNGEM_NREGS;		}		regs.version = 0;		if (copy_to_user(useraddr, &regs, sizeof(regs)))			return -EFAULT;		if (!gp->hw_running)			return -ENODEV;		useraddr += offsetof(struct ethtool_regs, data);		/* Use kmalloc to avoid bloating the stack */		regbuf = kmalloc(4 * SUNGEM_NREGS, GFP_KERNEL);		if (!regbuf)			return -ENOMEM;		spin_lock_irq(&np->lock);		gem_get_regs(gp, regbuf);		spin_unlock_irq(&np->lock);		if (copy_to_user(useraddr, regbuf, regs.len*sizeof(u32)))			r = -EFAULT;		kfree(regbuf);		return r;	}#endif		};	return -EOPNOTSUPP;}static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){	struct gem *gp = dev->priv;	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data;	int rc = -EOPNOTSUPP;		/* Hold the PM semaphore while doing ioctl's or we may collide	 * with open/close and power management and oops.	 */	down(&gp->pm_sem);		switch (cmd) {	case SIOCETHTOOL:		rc = gem_ethtool_ioctl(dev, ifr->ifr_data);		break;	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */		data->phy_id = gp->mii_phy_addr;		/* Fallthrough... */	case SIOCGMIIREG:		/* Read MII PHY register. */		data->val_out = __phy_read(gp, data->reg_num & 0x1f, data->phy_id & 0x1f);		rc = 0;		break;	case SIOCSMIIREG:		/* Write MII PHY register. */		if (!capable(CAP_NET_ADMIN)) {			rc = -EPERM;		} else {			__phy_write(gp, data->reg_num & 0x1f, data->val_in, data->phy_id & 0x1f);			rc = 0;		}		break;	};	up(&gp->pm_sem);		return rc;}static int __devinit gem_get_device_address(struct gem *gp){#if defined(__sparc__) || defined(CONFIG_ALL_PPC)	struct net_device *dev = gp->dev;#endif#ifdef __sparc__	struct pci_dev *pdev = gp->pdev;	struct pcidev_cookie *pcp = pdev->sysdata;	int node = -1;	if (pcp != NULL) {		node = pcp->prom_node;		if (prom_getproplen(node, "local-mac-address") == 6)			prom_getproperty(node, "local-mac-address",					 dev->dev_addr, 6);		else			node = -1;	}	if (node == -1)		memcpy(dev->dev_addr, idprom->id_ethaddr, 6);#endif#ifdef CONFIG_ALL_PPC	unsigned char *addr;	addr = get_property(gp->of_node, "local-mac-address", NULL);	if (addr == NULL) {		printk("\n");		printk(KERN_ERR "%s: can't get mac-address\n", dev->name);		return -1;	}	memcpy(dev->dev_addr, addr, MAX_ADDR_LEN);#endif	return 0;}static int __devinit gem_init_one(struct pci_dev *pdev,				  const struct pci_device_id *ent){	static int gem_version_printed = 0;	unsigned long gemreg_base, gemreg_len;	struct net_device *dev;	struct gem *

⌨️ 快捷键说明

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