欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

ewrk3.c

Linux Kernel 2.6.9 for OMAP1710
C
第 1 页 / 共 4 页
字号:
	return status;		/* return the device name string */}static int ewrk3_ethtool_ioctl(struct net_device *dev, void __user *useraddr){	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;	u_long iobase = dev->base_addr;	u32 ethcmd;	if (get_user(ethcmd, (u32 __user *)useraddr))		return -EFAULT;	switch (ethcmd) {	/* Get driver info */	case ETHTOOL_GDRVINFO: {		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };		int fwrev = Read_EEPROM(dev->base_addr, EEPROM_REVLVL);		strcpy(info.driver, DRV_NAME);		strcpy(info.version, DRV_VERSION);		sprintf(info.fw_version, "%d", fwrev);		strcpy(info.bus_info, "N/A");		info.eedump_len = EEPROM_MAX;		if (copy_to_user(useraddr, &info, sizeof(info)))			return -EFAULT;		return 0;	}	/* Get settings */	case ETHTOOL_GSET: {		struct ethtool_cmd ecmd = { ETHTOOL_GSET };		u_char cr = inb(EWRK3_CR);		switch (lp->adapter_name[4]) {		case '3': /* DE203 */			ecmd.supported = SUPPORTED_BNC;			ecmd.port = PORT_BNC;			break;		case '4': /* DE204 */			ecmd.supported = SUPPORTED_TP;			ecmd.port = PORT_TP;			break;		case '5': /* DE205 */			ecmd.supported = SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_AUI;			ecmd.autoneg = !(cr & CR_APD);			/*			** Port is only valid if autoneg is disabled			** and even then we don't know if AUI is jumpered.			*/			if (!ecmd.autoneg)				ecmd.port = (cr & CR_PSEL) ? PORT_BNC : PORT_TP;			break;		}		ecmd.supported |= SUPPORTED_10baseT_Half;		ecmd.speed = SPEED_10;		ecmd.duplex = DUPLEX_HALF;		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))			return -EFAULT;		return 0;	}	/* Set settings */	case ETHTOOL_SSET: {		struct ethtool_cmd ecmd;		u_char cr;		u_long flags;		/* DE205 is the only card with anything to set */		if (lp->adapter_name[4] != '5')			return -EOPNOTSUPP;		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))			return -EFAULT;		/* Sanity-check parameters */		if (ecmd.speed != SPEED_10)			return -EINVAL;		if (ecmd.port != PORT_TP && ecmd.port != PORT_BNC)			return -EINVAL; /* AUI is not software-selectable */		if (ecmd.transceiver != XCVR_INTERNAL)			return -EINVAL;		if (ecmd.duplex != DUPLEX_HALF)			return -EINVAL;		if (ecmd.phy_address != 0)			return -EINVAL;		spin_lock_irqsave(&lp->hw_lock, flags);		cr = inb(EWRK3_CR);		/* If Autoneg is set, change to Auto Port mode */		/* Otherwise, disable Auto Port and set port explicitly */		if (ecmd.autoneg) {			cr &= ~CR_APD;		} else {			cr |= CR_APD;			if (ecmd.port == PORT_TP)				cr &= ~CR_PSEL;		/* Force TP */			else				cr |= CR_PSEL;		/* Force BNC */		}		/* Commit the changes */		outb(cr, EWRK3_CR);		spin_unlock_irqrestore(&lp->hw_lock, flags);		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))			return -EFAULT;		return 0;	}	/* Get link status */	case ETHTOOL_GLINK: {		struct ethtool_value edata = { ETHTOOL_GLINK };		u_char cmr = inb(EWRK3_CMR);		/* DE203 has BNC only and link status does not apply */		if (lp->adapter_name[4] == '3')			return -EOPNOTSUPP;		/* On DE204 this is always valid since TP is the only port. */		/* On DE205 this reflects TP status even if BNC or AUI is selected. */		edata.data = !(cmr & CMR_LINK);		if (copy_to_user(useraddr, &edata, sizeof(edata)))			return -EFAULT;		return 0;	}	/* Blink LED for identification */	case ETHTOOL_PHYS_ID: {		struct ethtool_value edata;		u_long flags;		u_char cr;		int count;		if (copy_from_user(&edata, useraddr, sizeof(edata)))			return -EFAULT;		/* Toggle LED 4x per second */		count = edata.data << 2;		spin_lock_irqsave(&lp->hw_lock, flags);		/* Bail if a PHYS_ID is already in progress */		if (lp->led_mask == 0) {			spin_unlock_irqrestore(&lp->hw_lock, flags);			return -EBUSY;		}		/* Prevent ISR from twiddling the LED */		lp->led_mask = 0;		while (count--) {			/* Toggle the LED */			cr = inb(EWRK3_CR);			outb(cr ^ CR_LED, EWRK3_CR);			/* Wait a little while */			spin_unlock_irqrestore(&lp->hw_lock, flags);			set_current_state(TASK_UNINTERRUPTIBLE);			schedule_timeout(HZ>>2);			spin_lock_irqsave(&lp->hw_lock, flags);			/* Exit if we got a signal */			if (signal_pending(current))				break;		}		lp->led_mask = CR_LED;		cr = inb(EWRK3_CR);		outb(cr & ~CR_LED, EWRK3_CR);		spin_unlock_irqrestore(&lp->hw_lock, flags);		return signal_pending(current) ? -ERESTARTSYS : 0;	}	}	return -EOPNOTSUPP;}/*   ** Perform IOCTL call functions here. Some are privileged operations and the   ** effective uid is checked in those cases. */static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;	struct ewrk3_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_ifru;	u_long iobase = dev->base_addr;	int i, j, status = 0;	u_char csr;	unsigned long flags;	union ewrk3_addr {		u_char addr[HASH_TABLE_LEN * ETH_ALEN];		u_short val[(HASH_TABLE_LEN * ETH_ALEN) >> 1];	};		union ewrk3_addr *tmp;	/* ethtool IOCTLs are handled elsewhere */	if (cmd == SIOCETHTOOL)		return ewrk3_ethtool_ioctl(dev, rq->ifr_data);	/* Other than ethtool, all we handle are private IOCTLs */	if (cmd != EWRK3IOCTL)		return -EOPNOTSUPP;	tmp = kmalloc(sizeof(union ewrk3_addr), GFP_KERNEL);	if(tmp==NULL)		return -ENOMEM;	switch (ioc->cmd) {	case EWRK3_GET_HWADDR:	/* Get the hardware address */		for (i = 0; i < ETH_ALEN; i++) {			tmp->addr[i] = dev->dev_addr[i];		}		ioc->len = ETH_ALEN;		if (copy_to_user(ioc->data, tmp->addr, ioc->len))			status = -EFAULT;		break;			case EWRK3_SET_HWADDR:	/* Set the hardware address */		if (capable(CAP_NET_ADMIN)) {			spin_lock_irqsave(&lp->hw_lock, flags);			csr = inb(EWRK3_CSR);			csr |= (CSR_TXD | CSR_RXD);			outb(csr, EWRK3_CSR);	/* Disable the TX and RX */			spin_unlock_irqrestore(&lp->hw_lock, flags);			if (copy_from_user(tmp->addr, ioc->data, ETH_ALEN)) {				status = -EFAULT;				break;			}			spin_lock_irqsave(&lp->hw_lock, flags);			for (i = 0; i < ETH_ALEN; i++) {				dev->dev_addr[i] = tmp->addr[i];				outb(tmp->addr[i], EWRK3_PAR0 + i);			}			csr = inb(EWRK3_CSR);			csr &= ~(CSR_TXD | CSR_RXD);	/* Enable the TX and RX */			outb(csr, EWRK3_CSR);			spin_unlock_irqrestore(&lp->hw_lock, flags);		} else {			status = -EPERM;		}		break;	case EWRK3_SET_PROM:	/* Set Promiscuous Mode */		if (capable(CAP_NET_ADMIN)) {			spin_lock_irqsave(&lp->hw_lock, flags);			csr = inb(EWRK3_CSR);			csr |= CSR_PME;			csr &= ~CSR_MCE;			outb(csr, EWRK3_CSR);			spin_unlock_irqrestore(&lp->hw_lock, flags);		} else {			status = -EPERM;		}		break;	case EWRK3_CLR_PROM:	/* Clear Promiscuous Mode */		if (capable(CAP_NET_ADMIN)) {			spin_lock_irqsave(&lp->hw_lock, flags);			csr = inb(EWRK3_CSR);			csr &= ~CSR_PME;			outb(csr, EWRK3_CSR);			spin_unlock_irqrestore(&lp->hw_lock, flags);		} else {			status = -EPERM;		}		break;	case EWRK3_GET_MCA:	/* Get the multicast address table */		spin_lock_irqsave(&lp->hw_lock, flags);		if (lp->shmem_length == IO_ONLY) {			outb(0, EWRK3_IOPR);			outw(PAGE0_HTE, EWRK3_PIR1);			for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) {				tmp->addr[i] = inb(EWRK3_DATA);			}		} else {			outb(0, EWRK3_MPR);			isa_memcpy_fromio(tmp->addr, lp->shmem_base + PAGE0_HTE, (HASH_TABLE_LEN >> 3));		}		spin_unlock_irqrestore(&lp->hw_lock, flags);		ioc->len = (HASH_TABLE_LEN >> 3);		if (copy_to_user(ioc->data, tmp->addr, ioc->len))			status = -EFAULT;		break;	case EWRK3_SET_MCA:	/* Set a multicast address */		if (capable(CAP_NET_ADMIN)) {			if (ioc->len > 1024)			{				status = -EINVAL;				break;			}			if (copy_from_user(tmp->addr, ioc->data, ETH_ALEN * ioc->len)) {				status = -EFAULT;				break;			}			set_multicast_list(dev);		} else {			status = -EPERM;		}		break;	case EWRK3_CLR_MCA:	/* Clear all multicast addresses */		if (capable(CAP_NET_ADMIN)) {			set_multicast_list(dev);		} else {			status = -EPERM;		}		break;	case EWRK3_MCA_EN:	/* Enable multicast addressing */		if (capable(CAP_NET_ADMIN)) {			spin_lock_irqsave(&lp->hw_lock, flags);			csr = inb(EWRK3_CSR);			csr |= CSR_MCE;			csr &= ~CSR_PME;			outb(csr, EWRK3_CSR);			spin_unlock_irqrestore(&lp->hw_lock, flags);		} else {			status = -EPERM;		}		break;	case EWRK3_GET_STATS: { /* Get the driver statistics */		struct ewrk3_stats *tmp_stats =        		kmalloc(sizeof(lp->pktStats), GFP_KERNEL);		if (!tmp_stats) {			status = -ENOMEM;			break;		}		spin_lock_irqsave(&lp->hw_lock, flags);		memcpy(tmp_stats, &lp->pktStats, sizeof(lp->pktStats));		spin_unlock_irqrestore(&lp->hw_lock, flags);		ioc->len = sizeof(lp->pktStats);		if (copy_to_user(ioc->data, tmp_stats, sizeof(lp->pktStats)))    			status = -EFAULT;		kfree(tmp_stats);		break;	}	case EWRK3_CLR_STATS:	/* Zero out the driver statistics */		if (capable(CAP_NET_ADMIN)) {			spin_lock_irqsave(&lp->hw_lock, flags);			memset(&lp->pktStats, 0, sizeof(lp->pktStats));			spin_unlock_irqrestore(&lp->hw_lock,flags);		} else {			status = -EPERM;		}		break;	case EWRK3_GET_CSR:	/* Get the CSR Register contents */		tmp->addr[0] = inb(EWRK3_CSR);		ioc->len = 1;		if (copy_to_user(ioc->data, tmp->addr, ioc->len))			status = -EFAULT;		break;	case EWRK3_SET_CSR:	/* Set the CSR Register contents */		if (capable(CAP_NET_ADMIN)) {			if (copy_from_user(tmp->addr, ioc->data, 1)) {				status = -EFAULT;				break;			}			outb(tmp->addr[0], EWRK3_CSR);		} else {			status = -EPERM;		}		break;	case EWRK3_GET_EEPROM:	/* Get the EEPROM contents */		if (capable(CAP_NET_ADMIN)) {			for (i = 0; i < (EEPROM_MAX >> 1); i++) {				tmp->val[i] = (short) Read_EEPROM(iobase, i);			}			i = EEPROM_MAX;			tmp->addr[i++] = inb(EWRK3_CMR);		/* Config/Management Reg. */			for (j = 0; j < ETH_ALEN; j++) {				tmp->addr[i++] = inb(EWRK3_PAR0 + j);			}			ioc->len = EEPROM_MAX + 1 + ETH_ALEN;			if (copy_to_user(ioc->data, tmp->addr, ioc->len))				status = -EFAULT;		} else {			status = -EPERM;		}		break;	case EWRK3_SET_EEPROM:	/* Set the EEPROM contents */		if (capable(CAP_NET_ADMIN)) {			if (copy_from_user(tmp->addr, ioc->data, EEPROM_MAX)) {				status = -EFAULT;				break;			}			for (i = 0; i < (EEPROM_MAX >> 1); i++) {				Write_EEPROM(tmp->val[i], iobase, i);			}		} else {			status = -EPERM;		}		break;	case EWRK3_GET_CMR:	/* Get the CMR Register contents */		tmp->addr[0] = inb(EWRK3_CMR);		ioc->len = 1;		if (copy_to_user(ioc->data, tmp->addr, ioc->len))			status = -EFAULT;		break;	case EWRK3_SET_TX_CUT_THRU:	/* Set TX cut through mode */		if (capable(CAP_NET_ADMIN)) {			lp->txc = 1;		} else {			status = -EPERM;		}		break;	case EWRK3_CLR_TX_CUT_THRU:	/* Clear TX cut through mode */		if (capable(CAP_NET_ADMIN)) {			lp->txc = 0;		} else {			status = -EPERM;		}		break;	default:		status = -EOPNOTSUPP;	}	kfree(tmp);	return status;}#ifdef MODULEstatic struct net_device *ewrk3_devs[MAX_NUM_EWRK3S];static int ndevs;static int io[MAX_NUM_EWRK3S+1] = { 0x300, 0, };/* '21' below should really be 'MAX_NUM_EWRK3S' */MODULE_PARM(io, "0-21i");MODULE_PARM(irq, "0-21i");MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address(es)");MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number(s)");static __exit void ewrk3_exit_module(void){	int i;	for( i=0; i<ndevs; i++ ) {		unregister_netdev(ewrk3_devs[i]);		release_region(ewrk3_devs[i]->base_addr, EWRK3_TOTAL_SIZE);		free_netdev(ewrk3_devs[i]);		ewrk3_devs[i] = NULL;	}}static __init int ewrk3_init_module(void){	int i=0;	while( io[i] && irq[i] ) {		struct net_device *dev			= alloc_etherdev(sizeof(struct ewrk3_private));		if (!dev)			break;		if (ewrk3_probe1(dev, io[i], irq[i]) != 0) {			free_netdev(dev);			break;		}		ewrk3_devs[ndevs++] = dev;		i++;	}	return ndevs ? 0 : -EIO;}/* Hack for breakage in new module stuff */module_exit(ewrk3_exit_module);module_init(ewrk3_init_module);#endif				/* MODULE */MODULE_LICENSE("GPL");/* * Local variables: *  compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c ewrk3.c" * *  compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c ewrk3.c" * End: */

⌨️ 快捷键说明

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