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

📄 ewrk3.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	   ewrk3_dev_index(char *s)){	int i = 0, j = 0;	for (; *s; s++) {		if (isdigit(*s)) {			j = 1;			i = (i * 10) + (*s - '0');		} else if (j)			break;	}	return i;}/*   ** Read the EWRK3 EEPROM using this routine */static int Read_EEPROM(u_long iobase, u_char eaddr){	int i;	outb((eaddr & 0x3f), EWRK3_PIR1);	/* set up 6 bits of address info */	outb(EEPROM_RD, EWRK3_IOPR);	/* issue read command */	for (i = 0; i < 5000; i++)		inb(EWRK3_CSR);	/* wait 1msec */	return inw(EWRK3_EPROM1);	/* 16 bits data return */}/*   ** Write the EWRK3 EEPROM using this routine */static int Write_EEPROM(short data, u_long iobase, u_char eaddr){	int i;	outb(EEPROM_WR_EN, EWRK3_IOPR);		/* issue write enable command */	for (i = 0; i < 5000; i++)		inb(EWRK3_CSR);	/* wait 1msec */	outw(data, EWRK3_EPROM1);	/* write data to register */	outb((eaddr & 0x3f), EWRK3_PIR1);	/* set up 6 bits of address info */	outb(EEPROM_WR, EWRK3_IOPR);	/* issue write command */	for (i = 0; i < 75000; i++)		inb(EWRK3_CSR);	/* wait 15msec */	outb(EEPROM_WR_DIS, EWRK3_IOPR);	/* issue write disable command */	for (i = 0; i < 5000; i++)		inb(EWRK3_CSR);	/* wait 1msec */	return 0;}/*   ** Look for a particular board name in the on-board EEPROM. */__initfunc(static void EthwrkSignature(char *name, char *eeprom_image)){	u_long i, j, k;	char *signatures[] = EWRK3_SIGNATURE;	strcpy(name, "");	for (i = 0; *signatures[i] != '\0' && *name == '\0'; i++) {		for (j = EEPROM_PNAME7, k = 0; j <= EEPROM_PNAME0 && k < strlen(signatures[i]); j++) {			if (signatures[i][k] == eeprom_image[j]) {	/* track signature */				k++;			} else {	/* lost signature; begin search again */				k = 0;			}		}		if (k == strlen(signatures[i])) {			for (k = 0; k < EWRK3_STRLEN; k++) {				name[k] = eeprom_image[EEPROM_PNAME7 + k];				name[EWRK3_STRLEN] = '\0';			}		}	}	return;			/* return the device name string */}/*   ** Look for a special sequence in the Ethernet station address PROM that   ** is common across all EWRK3 products.   **   ** Search the Ethernet address ROM for the signature. Since the ROM address   ** counter can start at an arbitrary point, the search must include the entire   ** probe sequence length plus the (length_of_the_signature - 1).   ** Stop the search IMMEDIATELY after the signature is found so that the   ** PROM address counter is correctly positioned at the start of the   ** ethernet address for later read out. */__initfunc(static int DevicePresent(u_long iobase)){	union {		struct {			u32 a;			u32 b;		} llsig;		char Sig[sizeof(u32) << 1];	}	dev;	short sigLength;	char data;	int i, j, status = 0;	dev.llsig.a = ETH_PROM_SIG;	dev.llsig.b = ETH_PROM_SIG;	sigLength = sizeof(u32) << 1;	for (i = 0, j = 0; j < sigLength && i < PROBE_LENGTH + sigLength - 1; i++) {		data = inb(EWRK3_APROM);		if (dev.Sig[j] == data) {	/* track signature */			j++;		} else {	/* lost signature; begin search again */			if (data == dev.Sig[0]) {				j = 1;			} else {				j = 0;			}		}	}	if (j != sigLength) {		status = -ENODEV;	/* search failed */	}	return status;}__initfunc(static u_char get_hw_addr(struct device *dev, u_char * eeprom_image, char chipType)){	int i, j, k;	u_short chksum;	u_char crc, lfsr, sd, status = 0;	u_long iobase = dev->base_addr;	u16 tmp;	if (chipType == LeMAC2) {		for (crc = 0x6a, j = 0; j < ETH_ALEN; j++) {			sd = dev->dev_addr[j] = eeprom_image[EEPROM_PADDR0 + j];			outb(dev->dev_addr[j], EWRK3_PAR0 + j);			for (k = 0; k < 8; k++, sd >>= 1) {				lfsr = ((((crc & 0x02) >> 1) ^ (crc & 0x01)) ^ (sd & 0x01)) << 7;				crc = (crc >> 1) + lfsr;			}		}		if (crc != eeprom_image[EEPROM_PA_CRC])			status = -1;	} else {		for (i = 0, k = 0; i < ETH_ALEN;) {			k <<= 1;			if (k > 0xffff)				k -= 0xffff;			k += (u_char) (tmp = inb(EWRK3_APROM));			dev->dev_addr[i] = (u_char) tmp;			outb(dev->dev_addr[i], EWRK3_PAR0 + i);			i++;			k += (u_short) ((tmp = inb(EWRK3_APROM)) << 8);			dev->dev_addr[i] = (u_char) tmp;			outb(dev->dev_addr[i], EWRK3_PAR0 + i);			i++;			if (k > 0xffff)				k -= 0xffff;		}		if (k == 0xffff)			k = 0;		chksum = inb(EWRK3_APROM);		chksum |= (inb(EWRK3_APROM) << 8);		if (k != chksum)			status = -1;	}	return status;}/*   ** Look for a particular board name in the EISA configuration space */__initfunc(static int EISA_signature(char *name, s32 eisa_id)){	u_long i;	char *signatures[] = EWRK3_SIGNATURE;	char ManCode[EWRK3_STRLEN];	union {		s32 ID;		char Id[4];	} Eisa;	int status = 0;	*name = '\0';	for (i = 0; i < 4; i++) {		Eisa.Id[i] = inb(eisa_id + i);	}	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 */}/*   ** Perform IOCTL call functions here. Some are privileged operations and the   ** effective uid is checked in those cases. */static int ewrk3_ioctl(struct 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_data;	u_long iobase = dev->base_addr;	int i, j, status = 0;	u_char csr;	union {		u_char addr[HASH_TABLE_LEN * ETH_ALEN];		u_short val[(HASH_TABLE_LEN * ETH_ALEN) >> 1];	} tmp;	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 (!(status = verify_area(VERIFY_WRITE, (void *) ioc->data, ioc->len))) {			copy_to_user(ioc->data, tmp.addr, ioc->len);		}		break;	case EWRK3_SET_HWADDR:	/* Set the hardware address */		if (capable(CAP_NET_ADMIN)) {			if (!(status = verify_area(VERIFY_READ, (void *) ioc->data, ETH_ALEN))) {				csr = inb(EWRK3_CSR);				csr |= (CSR_TXD | CSR_RXD);				outb(csr, EWRK3_CSR);	/* Disable the TX and RX */				copy_from_user(tmp.addr, ioc->data, ETH_ALEN);				for (i = 0; i < ETH_ALEN; i++) {					dev->dev_addr[i] = tmp.addr[i];					outb(tmp.addr[i], EWRK3_PAR0 + i);				}				csr &= ~(CSR_TXD | CSR_RXD);	/* Enable the TX and RX */				outb(csr, EWRK3_CSR);			}		} else {			status = -EPERM;		}		break;	case EWRK3_SET_PROM:	/* Set Promiscuous Mode */		if (capable(CAP_NET_ADMIN)) {			csr = inb(EWRK3_CSR);			csr |= CSR_PME;			csr &= ~CSR_MCE;			outb(csr, EWRK3_CSR);		} else {			status = -EPERM;		}		break;	case EWRK3_CLR_PROM:	/* Clear Promiscuous Mode */		if (capable(CAP_NET_ADMIN)) {			csr = inb(EWRK3_CSR);			csr &= ~CSR_PME;			outb(csr, EWRK3_CSR);		} else {			status = -EPERM;		}		break;	case EWRK3_SAY_BOO:	/* Say "Boo!" to the kernel log file */		printk("%s: Boo!\n", dev->name);		break;	case EWRK3_GET_MCA:	/* Get the multicast address table */		if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {			while (test_and_set_bit(0, (void *) &lp->lock) != 0);	/* Wait for lock to free */			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, (char *) (lp->shmem_base + PAGE0_HTE), (HASH_TABLE_LEN >> 3));			}			ioc->len = (HASH_TABLE_LEN >> 3);			copy_to_user(ioc->data, tmp.addr, ioc->len);		}		lp->lock = 0;	/* Unlock the page register */		break;	case EWRK3_SET_MCA:	/* Set a multicast address */		if (capable(CAP_NET_ADMIN)) {			if (!(status = verify_area(VERIFY_READ, ioc->data, ETH_ALEN * ioc->len))) {				copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len);				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)) {			csr = inb(EWRK3_CSR);			csr |= CSR_MCE;			csr &= ~CSR_PME;			outb(csr, EWRK3_CSR);		} else {			status = -EPERM;		}		break;	case EWRK3_GET_STATS:	/* Get the driver statistics */		cli();		ioc->len = sizeof(lp->pktStats);		if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {			copy_to_user(ioc->data, &lp->pktStats, ioc->len);		}		sti();		break;	case EWRK3_CLR_STATS:	/* Zero out the driver statistics */		if (capable(CAP_NET_ADMIN)) {			cli();			memset(&lp->pktStats, 0, sizeof(lp->pktStats));			sti();		} else {			status = -EPERM;		}		break;	case EWRK3_GET_CSR:	/* Get the CSR Register contents */		tmp.addr[0] = inb(EWRK3_CSR);		ioc->len = 1;		if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {			copy_to_user(ioc->data, tmp.addr, ioc->len);		}		break;	case EWRK3_SET_CSR:	/* Set the CSR Register contents */		if (capable(CAP_NET_ADMIN)) {			if (!(status = verify_area(VERIFY_READ, ioc->data, 1))) {				copy_from_user(tmp.addr, ioc->data, 1);				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 (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {				copy_to_user(ioc->data, tmp.addr, ioc->len);			}		} else {			status = -EPERM;		}		break;	case EWRK3_SET_EEPROM:	/* Set the EEPROM contents */		if (capable(CAP_NET_ADMIN)) {			if (!(status = verify_area(VERIFY_READ, ioc->data, EEPROM_MAX))) {				copy_from_user(tmp.addr, ioc->data, EEPROM_MAX);				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 (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {			copy_to_user(ioc->data, tmp.addr, ioc->len);		}		break;	case EWRK3_SET_TX_CUT_THRU:	/* Set TX cut through mode */		if (suser()) {			lp->txc = 1;		} else {			status = -EPERM;		}		break;	case EWRK3_CLR_TX_CUT_THRU:	/* Clear TX cut through mode */		if (suser()) {			lp->txc = 0;		} else {			status = -EPERM;		}		break;	default:		status = -EOPNOTSUPP;	}	return status;}#ifdef MODULEstatic char devicename[9] ={0,};static struct device thisEthwrk ={	devicename,		/* device name is inserted by /linux/drivers/net/net_init.c */	0, 0, 0, 0,	0x300, 5,		/* I/O address, IRQ */	0, 0, 0, NULL, ewrk3_probe};static int io = 0x300;		/* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */static int irq = 5;		/* or use the insmod io= irq= options           */MODULE_PARM(io, "i");MODULE_PARM(irq, "i");int init_module(void){	thisEthwrk.base_addr = io;	thisEthwrk.irq = irq;	if (register_netdev(&thisEthwrk) != 0)		return -EIO;	return 0;}void cleanup_module(void){	unregister_netdev(&thisEthwrk);	if (thisEthwrk.priv) {		kfree(thisEthwrk.priv);		thisEthwrk.priv = NULL;	}	thisEthwrk.irq = 0;	release_region(thisEthwrk.base_addr, EWRK3_TOTAL_SIZE);}#endif				/* MODULE *//* * 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 + -