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

📄 natsemi.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
			set_bit_le(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff,					mc_filter);		}		rx_mode = RxFilterEnable | AcceptBroadcast 			| AcceptMulticast | AcceptMyPhys;		for (i = 0; i < 64; i += 2) {			writew(HASH_TABLE + i, ioaddr + RxFilterAddr);			writew((mc_filter[i+1]<<8) + mc_filter[i], 				ioaddr + RxFilterData);		}	}	writel(rx_mode, ioaddr + RxFilterAddr);	np->cur_rx_mode = rx_mode;}static void set_rx_mode(struct net_device *dev){	struct netdev_private *np = dev->priv;	spin_lock_irq(&np->lock);	if (netif_device_present(dev))		__set_rx_mode(dev);	spin_unlock_irq(&np->lock);}static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr){	struct netdev_private *np = dev->priv;	u32 cmd;		if (get_user(cmd, (u32 *)useraddr))		return -EFAULT;        switch (cmd) {	/* get driver info */        case ETHTOOL_GDRVINFO: {		struct ethtool_drvinfo info = {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, np->pci_dev->slot_name, 			ETHTOOL_BUSINFO_LEN);		info.eedump_len = NATSEMI_EEPROM_SIZE;		info.regdump_len = NATSEMI_REGS_SIZE;		if (copy_to_user(useraddr, &info, sizeof(info)))			return -EFAULT;		return 0;	}	/* get settings */	case ETHTOOL_GSET: {		struct ethtool_cmd ecmd = { ETHTOOL_GSET };		spin_lock_irq(&np->lock);		netdev_get_ecmd(dev, &ecmd);		spin_unlock_irq(&np->lock);		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))			return -EFAULT;		return 0;	}	/* set settings */	case ETHTOOL_SSET: {		struct ethtool_cmd ecmd;		int r;		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))			return -EFAULT;		spin_lock_irq(&np->lock);		r = netdev_set_ecmd(dev, &ecmd);		spin_unlock_irq(&np->lock);		return r;	}	/* get wake-on-lan */	case ETHTOOL_GWOL: {		struct ethtool_wolinfo wol = {ETHTOOL_GWOL};		spin_lock_irq(&np->lock);		netdev_get_wol(dev, &wol.supported, &wol.wolopts);		netdev_get_sopass(dev, wol.sopass);		spin_unlock_irq(&np->lock);		if (copy_to_user(useraddr, &wol, sizeof(wol)))			return -EFAULT;		return 0;	}	/* set wake-on-lan */	case ETHTOOL_SWOL: {		struct ethtool_wolinfo wol;		int r;		if (copy_from_user(&wol, useraddr, sizeof(wol)))			return -EFAULT;		spin_lock_irq(&np->lock);		netdev_set_wol(dev, wol.wolopts);		r = netdev_set_sopass(dev, wol.sopass);		spin_unlock_irq(&np->lock);		return r;	}	/* get registers */	case ETHTOOL_GREGS: {		struct ethtool_regs regs;		u8 regbuf[NATSEMI_REGS_SIZE];		int r;		if (copy_from_user(&regs, useraddr, sizeof(regs)))			return -EFAULT;				if (regs.len > NATSEMI_REGS_SIZE) {			regs.len = NATSEMI_REGS_SIZE;		}		regs.version = NATSEMI_REGS_VER;		if (copy_to_user(useraddr, &regs, sizeof(regs)))			return -EFAULT;		useraddr += offsetof(struct ethtool_regs, data);		spin_lock_irq(&np->lock);		r = netdev_get_regs(dev, regbuf);		spin_unlock_irq(&np->lock);		if (r)			return r;		if (copy_to_user(useraddr, regbuf, regs.len))			return -EFAULT;		return 0;	}	/* get message-level */	case ETHTOOL_GMSGLVL: {		struct ethtool_value edata = {ETHTOOL_GMSGLVL};		edata.data = np->msg_enable;		if (copy_to_user(useraddr, &edata, sizeof(edata)))			return -EFAULT;		return 0;	}	/* set message-level */	case ETHTOOL_SMSGLVL: {		struct ethtool_value edata;		if (copy_from_user(&edata, useraddr, sizeof(edata)))			return -EFAULT;		np->msg_enable = edata.data;		return 0;	}	/* restart autonegotiation */	case ETHTOOL_NWAY_RST: {		int tmp;		int r = -EINVAL;		/* if autoneg is off, it's an error */		tmp = mdio_read(dev, 1, MII_BMCR);		if (tmp & BMCR_ANENABLE) {			tmp |= (BMCR_ANRESTART);			mdio_write(dev, 1, MII_BMCR, tmp);			r = 0;		}		return r;	}	/* get link status */	case ETHTOOL_GLINK: {		struct ethtool_value edata = {ETHTOOL_GLINK};		edata.data = (mdio_read(dev, 1, MII_BMSR)&BMSR_LSTATUS) ? 1:0;		if (copy_to_user(useraddr, &edata, sizeof(edata)))			return -EFAULT;		return 0;	}	/* get EEPROM */	case ETHTOOL_GEEPROM: {		struct ethtool_eeprom eeprom;		u8 eebuf[NATSEMI_EEPROM_SIZE];		int r;		if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))			return -EFAULT;				if ((eeprom.offset+eeprom.len) > NATSEMI_EEPROM_SIZE) {			eeprom.len = NATSEMI_EEPROM_SIZE-eeprom.offset;		}		eeprom.magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16);		if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))			return -EFAULT;		useraddr += offsetof(struct ethtool_eeprom, data);		spin_lock_irq(&np->lock);		r = netdev_get_eeprom(dev, eebuf);		spin_unlock_irq(&np->lock);		if (r)			return r;		if (copy_to_user(useraddr, eebuf+eeprom.offset, eeprom.len))			return -EFAULT;		return 0;	}        }		return -EOPNOTSUPP;}static int netdev_set_wol(struct net_device *dev, u32 newval){	struct netdev_private *np = dev->priv;	u32 data = readl(dev->base_addr + WOLCmd) & ~WakeOptsSummary;	/* translate to bitmasks this chip understands */	if (newval & WAKE_PHY)		data |= WakePhy;	if (newval & WAKE_UCAST)		data |= WakeUnicast;	if (newval & WAKE_MCAST)		data |= WakeMulticast;	if (newval & WAKE_BCAST)		data |= WakeBroadcast;	if (newval & WAKE_ARP)		data |= WakeArp;	if (newval & WAKE_MAGIC)		data |= WakeMagic;	if (np->srr >= SRR_REV_D) {		if (newval & WAKE_MAGICSECURE) {			data |= WakeMagicSecure;		}	}	writel(data, dev->base_addr + WOLCmd);	return 0;}static int netdev_get_wol(struct net_device *dev, u32 *supported, u32 *cur){	struct netdev_private *np = dev->priv;	u32 regval = readl(dev->base_addr + WOLCmd);	*supported = (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST 			| WAKE_ARP | WAKE_MAGIC);		if (np->srr >= SRR_REV_D) {		/* SOPASS works on revD and higher */		*supported |= WAKE_MAGICSECURE;	}	*cur = 0;	/* translate from chip bitmasks */	if (regval & WakePhy)		*cur |= WAKE_PHY;	if (regval & WakeUnicast)		*cur |= WAKE_UCAST;	if (regval & WakeMulticast)		*cur |= WAKE_MCAST;	if (regval & WakeBroadcast)		*cur |= WAKE_BCAST;	if (regval & WakeArp)		*cur |= WAKE_ARP;	if (regval & WakeMagic)		*cur |= WAKE_MAGIC;	if (regval & WakeMagicSecure) {		/* this can be on in revC, but it's broken */		*cur |= WAKE_MAGICSECURE;	}	return 0;}static int netdev_set_sopass(struct net_device *dev, u8 *newval){	struct netdev_private *np = dev->priv;	u16 *sval = (u16 *)newval;	u32 addr;		if (np->srr < SRR_REV_D) {		return 0;	}	/* enable writing to these registers by disabling the RX filter */	addr = readl(dev->base_addr + RxFilterAddr) & ~RFCRAddressMask;	addr &= ~RxFilterEnable;	writel(addr, dev->base_addr + RxFilterAddr);	/* write the three words to (undocumented) RFCR vals 0xa, 0xc, 0xe */	writel(addr | 0xa, dev->base_addr + RxFilterAddr);	writew(sval[0], dev->base_addr + RxFilterData);	writel(addr | 0xc, dev->base_addr + RxFilterAddr);	writew(sval[1], dev->base_addr + RxFilterData);		writel(addr | 0xe, dev->base_addr + RxFilterAddr);	writew(sval[2], dev->base_addr + RxFilterData);		/* re-enable the RX filter */	writel(addr | RxFilterEnable, dev->base_addr + RxFilterAddr);	return 0;}static int netdev_get_sopass(struct net_device *dev, u8 *data){	struct netdev_private *np = dev->priv;	u16 *sval = (u16 *)data;	u32 addr;	if (np->srr < SRR_REV_D) {		sval[0] = sval[1] = sval[2] = 0;		return 0;	}	/* read the three words from (undocumented) RFCR vals 0xa, 0xc, 0xe */	addr = readl(dev->base_addr + RxFilterAddr) & ~RFCRAddressMask;	writel(addr | 0xa, dev->base_addr + RxFilterAddr);	sval[0] = readw(dev->base_addr + RxFilterData);	writel(addr | 0xc, dev->base_addr + RxFilterAddr);	sval[1] = readw(dev->base_addr + RxFilterData);		writel(addr | 0xe, dev->base_addr + RxFilterAddr);	sval[2] = readw(dev->base_addr + RxFilterData);		writel(addr, dev->base_addr + RxFilterAddr);	return 0;}static int netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd){	u32 tmp;	ecmd->supported = 		(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |		SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |		SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);		/* only supports twisted-pair or MII */	tmp = readl(dev->base_addr + ChipConfig);	if (tmp & CfgExtPhy)		ecmd->port = PORT_MII;	else		ecmd->port = PORT_TP;	/* only supports internal transceiver */	ecmd->transceiver = XCVR_INTERNAL;	/* not sure what this is for */	ecmd->phy_address = readw(dev->base_addr + PhyCtrl) & PhyAddrMask;	ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;	tmp = mdio_read(dev, 1, MII_ADVERTISE);	if (tmp & ADVERTISE_10HALF)		ecmd->advertising |= ADVERTISED_10baseT_Half;	if (tmp & ADVERTISE_10FULL)		ecmd->advertising |= ADVERTISED_10baseT_Full;	if (tmp & ADVERTISE_100HALF)		ecmd->advertising |= ADVERTISED_100baseT_Half;	if (tmp & ADVERTISE_100FULL)		ecmd->advertising |= ADVERTISED_100baseT_Full;	tmp = mdio_read(dev, 1, MII_BMCR);	if (tmp & BMCR_ANENABLE) {		ecmd->advertising |= ADVERTISED_Autoneg;		ecmd->autoneg = AUTONEG_ENABLE;	} else {		ecmd->autoneg = AUTONEG_DISABLE;	}	tmp = readl(dev->base_addr + ChipConfig);	if (tmp & CfgSpeed100) {		ecmd->speed = SPEED_100;	} else {		ecmd->speed = SPEED_10;	}			if (tmp & CfgFullDuplex) {		ecmd->duplex = DUPLEX_FULL;	} else {		ecmd->duplex = DUPLEX_HALF;	}	/* ignore maxtxpkt, maxrxpkt for now */	return 0;}static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd){	struct netdev_private *np = dev->priv;	u32 tmp;	if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)		return -EINVAL;	if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)		return -EINVAL;	if (ecmd->port != PORT_TP && ecmd->port != PORT_MII)		return -EINVAL;	if (ecmd->transceiver != XCVR_INTERNAL)		return -EINVAL;	if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)		return -EINVAL;	/* ignore phy_address, maxtxpkt, maxrxpkt for now */		/* WHEW! now lets bang some bits */		tmp = mdio_read(dev, 1, MII_BMCR);	if (ecmd->autoneg == AUTONEG_ENABLE) {		/* turn on autonegotiation */		tmp |= BMCR_ANENABLE;		np->advertising = mdio_read(dev, 1, MII_ADVERTISE);	} else {		/* turn off auto negotiation, set speed and duplexity */		tmp &= ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);		if (ecmd->speed == SPEED_100)			tmp |= BMCR_SPEED100;		if (ecmd->duplex == DUPLEX_FULL)			tmp |= BMCR_FULLDPLX;		else			np->full_duplex = 0;	}	mdio_write(dev, 1, MII_BMCR, tmp);	return 0;}static int netdev_get_regs(struct net_device *dev, u8 *buf){	int i;	int j;	u32 rfcr;	u32 *rbuf = (u32 *)buf;		/* read all of page 0 of registers */	for (i = 0; i < NATSEMI_PG0_NREGS; i++) {		rbuf[i] = readl(dev->base_addr + i*4);	}	/* read only the 'magic' registers from page 1 */	writew(1, dev->base_addr + PGSEL);	rbuf[i++] = readw(dev->base_addr + PMDCSR);	rbuf[i++] = readw(dev->base_addr + TSTDAT);	rbuf[i++] = readw(dev->base_addr + DSPCFG);	rbuf[i++] = readw(dev->base_addr + SDCFG);	writew(0, dev->base_addr + PGSEL);	/* read RFCR indexed registers */	rfcr = readl(dev->base_addr + RxFilterAddr);	for (j = 0; j < NATSEMI_RFDR_NREGS; j++) {		writel(j*2, dev->base_addr + RxFilterAddr);		rbuf[i++] = readw(dev->base_addr + RxFilterData);	}	writel(rfcr, dev->base_addr + RxFilterAddr);	/* the interrupt status is clear-on-read - see if we missed any */	if (rbuf[4] & rbuf[5]) {		printk(KERN_WARNING 			"%s: shoot, we dropped an interrupt (%#08x)\n", 			dev->name, rbuf[4] & rbuf[5]);	}	return 0;}#define SWAP_BITS(x)	( (((x) & 0x0001) << 15) | (((x) & 0x0002) << 13) \			| (((x) & 0x0004) << 11) | (((x) & 0x0008) << 9)  \			| (((x) & 0x0010) << 7)  | (((x) & 0x0020) << 5)  \			| (((x) & 0x0040) << 3)  | (((x) & 0

⌨️ 快捷键说明

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