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

ewrk3.c

linux 内核源代码
C
第 1 页 / 共 4 页
字号:
	ManCode[0] = (((Eisa.Id[0] >> 2) & 0x1f) + 0x40);	ManCode[1] = (((Eisa.Id[1] & 0xe0) >> 5) + ((Eisa.Id[0] & 0x03) << 3) + 0x40);	ManCode[2] = (((Eisa.Id[2] >> 4) & 0x0f) + 0x30);	ManCode[3] = ((Eisa.Id[2] & 0x0f) + 0x30);	ManCode[4] = (((Eisa.Id[3] >> 4) & 0x0f) + 0x30);	ManCode[5] = '\0';	for (i = 0; (*signatures[i] != '\0') && (*name == '\0'); i++) {		if (strstr(ManCode, signatures[i]) != NULL) {			strcpy(name, ManCode);			status = 1;		}	}	return status;		/* return the device name string */}static void ewrk3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info){	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;}static int ewrk3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd){	struct ewrk3_private *lp = netdev_priv(dev);	unsigned long iobase = dev->base_addr;	u8 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;	return 0;}static int ewrk3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd){	struct ewrk3_private *lp = netdev_priv(dev);	unsigned long iobase = dev->base_addr;	unsigned long flags;	u8 cr;	/* DE205 is the only card with anything to set */	if (lp->adapter_name[4] != '5')		return -EOPNOTSUPP;	/* 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);	return 0;}static u32 ewrk3_get_link(struct net_device *dev){	unsigned long iobase = dev->base_addr;	u8 cmr = inb(EWRK3_CMR);	/* DE203 has BNC only and link status does not apply */	/* 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. */	return !(cmr & CMR_LINK);}static int ewrk3_phys_id(struct net_device *dev, u32 data){	struct ewrk3_private *lp = netdev_priv(dev);	unsigned long iobase = dev->base_addr;	unsigned long flags;	u8 cr;	int count;	/* Toggle LED 4x per second */	count = 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);		msleep(250);		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;}static const struct ethtool_ops ethtool_ops_203 = {	.get_drvinfo = ewrk3_get_drvinfo,	.get_settings = ewrk3_get_settings,	.set_settings = ewrk3_set_settings,	.phys_id = ewrk3_phys_id,};static const struct ethtool_ops ethtool_ops = {	.get_drvinfo = ewrk3_get_drvinfo,	.get_settings = ewrk3_get_settings,	.set_settings = ewrk3_set_settings,	.get_link = ewrk3_get_link,	.phys_id = ewrk3_phys_id,};/*   ** 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 = netdev_priv(dev);	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;	/* 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);			memcpy_fromio(tmp->addr, lp->shmem + 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_param_array(io, int, NULL, 0);module_param_array(irq, int, NULL, 0);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++ ) {		struct net_device *dev = ewrk3_devs[i];		struct ewrk3_private *lp = netdev_priv(dev);		ewrk3_devs[i] = NULL;		unregister_netdev(dev);		release_region(dev->base_addr, EWRK3_TOTAL_SIZE);		iounmap(lp->shmem);		free_netdev(dev);	}}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 + -