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

ewrk3.c

linux 内核源代码
C
第 1 页 / 共 4 页
字号:
							for (i = 0; i < pkt_len; i++) {								*p++ = inb(EWRK3_DATA);							}						} else {							memcpy_fromio(p, buf, pkt_len);						}						for (i = 1; i < EWRK3_PKT_STAT_SZ - 1; i++) {							if (pkt_len < i * EWRK3_PKT_BIN_SZ) {								lp->pktStats.bins[i]++;								i = EWRK3_PKT_STAT_SZ;							}						}						p = skb->data;	/* Look at the dest addr */						if (p[0] & 0x01) {	/* Multicast/Broadcast */							if ((*(s16 *) & p[0] == -1) && (*(s16 *) & p[2] == -1) && (*(s16 *) & p[4] == -1)) {								lp->pktStats.broadcast++;							} else {								lp->pktStats.multicast++;							}						} else if ((*(s16 *) & p[0] == *(s16 *) & dev->dev_addr[0]) &&							   (*(s16 *) & p[2] == *(s16 *) & dev->dev_addr[2]) &&							   (*(s16 *) & p[4] == *(s16 *) & dev->dev_addr[4])) {							lp->pktStats.unicast++;						}						lp->pktStats.bins[0]++;		/* Duplicates stats.rx_packets */						if (lp->pktStats.bins[0] == 0) {	/* Reset counters */							memset(&lp->pktStats, 0, sizeof(lp->pktStats));						}						/*						   ** Notify the upper protocol layers that there is another						   ** packet to handle						 */						skb->protocol = eth_type_trans(skb, dev);						netif_rx(skb);						/*						   ** Update stats						 */						dev->last_rx = jiffies;						dev->stats.rx_packets++;						dev->stats.rx_bytes += pkt_len;					} else {						printk("%s: Insufficient memory; nuking packet.\n", dev->name);						dev->stats.rx_dropped++;		/* Really, deferred. */						break;					}				}			}			/*			   ** Return the received buffer to the free memory queue			 */			outb(page, EWRK3_FMQ);		} else {			printk("ewrk3_rx(): Illegal page number, page %d\n", page);			printk("ewrk3_rx(): CSR: %02x ICR: %02x FMQC: %02x\n", inb(EWRK3_CSR), inb(EWRK3_ICR), inb(EWRK3_FMQC));		}	}	return status;}/*** Buffer sent - check for TX buffer errors.** Called with lp->hw_lock held*/static int ewrk3_tx(struct net_device *dev){	struct ewrk3_private *lp = netdev_priv(dev);	u_long iobase = dev->base_addr;	u_char tx_status;	while ((tx_status = inb(EWRK3_TDQ)) > 0) {	/* Whilst there's old buffers */		if (tx_status & T_VSTS) {	/* The status is valid */			if (tx_status & T_TXE) {				dev->stats.tx_errors++;				if (tx_status & T_NCL)					dev->stats.tx_carrier_errors++;				if (tx_status & T_LCL)					dev->stats.tx_window_errors++;				if (tx_status & T_CTU) {					if ((tx_status & T_COLL) ^ T_XUR) {						lp->pktStats.tx_underruns++;					} else {						lp->pktStats.excessive_underruns++;					}				} else if (tx_status & T_COLL) {					if ((tx_status & T_COLL) ^ T_XCOLL) {						dev->stats.collisions++;					} else {						lp->pktStats.excessive_collisions++;					}				}			} else {				dev->stats.tx_packets++;			}		}	}	return 0;}static int ewrk3_close(struct net_device *dev){	struct ewrk3_private *lp = netdev_priv(dev);	u_long iobase = dev->base_addr;	u_char icr, csr;	netif_stop_queue(dev);	if (ewrk3_debug > 1) {		printk("%s: Shutting down ethercard, status was %2.2x.\n",		       dev->name, inb(EWRK3_CSR));	}	/*	   ** We stop the EWRK3 here... mask interrupts and stop TX & RX	 */	DISABLE_IRQs;	STOP_EWRK3;	/*	   ** Clean out the TX and RX queues here (note that one entry	   ** may get added to either the TXD or RX queues if the TX or RX	   ** just starts processing a packet before the STOP_EWRK3 command	   ** is received. This will be flushed in the ewrk3_open() call).	 */	while (inb(EWRK3_TQ));	while (inb(EWRK3_TDQ));	while (inb(EWRK3_RQ));	if (!lp->hard_strapped) {		free_irq(dev->irq, dev);	}	return 0;}/*   ** Set or clear the multicast filter for this adapter. */static void set_multicast_list(struct net_device *dev){	struct ewrk3_private *lp = netdev_priv(dev);	u_long iobase = dev->base_addr;	u_char csr;	csr = inb(EWRK3_CSR);	if (lp->shmem_length == IO_ONLY) {		lp->mctbl = NULL;	} else {		lp->mctbl = lp->shmem + PAGE0_HTE;	}	csr &= ~(CSR_PME | CSR_MCE);	if (dev->flags & IFF_PROMISC) {		/* set promiscuous mode */		csr |= CSR_PME;		outb(csr, EWRK3_CSR);	} else {		SetMulticastFilter(dev);		csr |= CSR_MCE;		outb(csr, EWRK3_CSR);	}}/*   ** Calculate the hash code and update the logical address filter   ** from a list of ethernet multicast addresses.   ** Little endian crc one liner from Matt Thomas, DEC.   **   ** Note that when clearing the table, the broadcast bit must remain asserted   ** to receive broadcast messages. */static void SetMulticastFilter(struct net_device *dev){	struct ewrk3_private *lp = netdev_priv(dev);	struct dev_mc_list *dmi = dev->mc_list;	u_long iobase = dev->base_addr;	int i;	char *addrs, bit, byte;	short __iomem *p = lp->mctbl;	u16 hashcode;	u32 crc;	spin_lock_irq(&lp->hw_lock);	if (lp->shmem_length == IO_ONLY) {		outb(0, EWRK3_IOPR);		outw(PAGE0_HTE, EWRK3_PIR1);	} else {		outb(0, EWRK3_MPR);	}	if (dev->flags & IFF_ALLMULTI) {		for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) {			if (lp->shmem_length == IO_ONLY) {				outb(0xff, EWRK3_DATA);			} else {	/* memset didn't work here */				writew(0xffff, p);				p++;				i++;			}		}	} else {		/* Clear table except for broadcast bit */		if (lp->shmem_length == IO_ONLY) {			for (i = 0; i < (HASH_TABLE_LEN >> 4) - 1; i++) {				outb(0x00, EWRK3_DATA);			}			outb(0x80, EWRK3_DATA);			i++;	/* insert the broadcast bit */			for (; i < (HASH_TABLE_LEN >> 3); i++) {				outb(0x00, EWRK3_DATA);			}		} else {			memset_io(lp->mctbl, 0, HASH_TABLE_LEN >> 3);			writeb(0x80, lp->mctbl + (HASH_TABLE_LEN >> 4) - 1);		}		/* Update table */		for (i = 0; i < dev->mc_count; i++) {	/* for each address in the list */			addrs = dmi->dmi_addr;			dmi = dmi->next;			if ((*addrs & 0x01) == 1) {	/* multicast address? */				crc = ether_crc_le(ETH_ALEN, addrs);				hashcode = crc & ((1 << 9) - 1);	/* hashcode is 9 LSb of CRC */				byte = hashcode >> 3;	/* bit[3-8] -> byte in filter */				bit = 1 << (hashcode & 0x07);	/* bit[0-2] -> bit in byte */				if (lp->shmem_length == IO_ONLY) {					u_char tmp;					outw(PAGE0_HTE + byte, EWRK3_PIR1);					tmp = inb(EWRK3_DATA);					tmp |= bit;					outw(PAGE0_HTE + byte, EWRK3_PIR1);					outb(tmp, EWRK3_DATA);				} else {					writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte);				}			}		}	}	spin_unlock_irq(&lp->hw_lock);}/*   ** ISA bus I/O device probe */static int __init isa_probe(struct net_device *dev, u_long ioaddr){	int i = num_ewrks3s, maxSlots;	int ret = -ENODEV;	u_long iobase;	if (ioaddr >= 0x400)		goto out;	if (ioaddr == 0) {	/* Autoprobing */		iobase = EWRK3_IO_BASE;		/* Get the first slot address */		maxSlots = 24;	} else {		/* Probe a specific location */		iobase = ioaddr;		maxSlots = i + 1;	}	for (; (i < maxSlots) && (dev != NULL);	     iobase += EWRK3_IOP_INC, i++)	{		if (request_region(iobase, EWRK3_TOTAL_SIZE, DRV_NAME)) {			if (DevicePresent(iobase) == 0) {				int irq = dev->irq;				ret = ewrk3_hw_init(dev, iobase);				if (!ret)					break;				dev->irq = irq;			}			release_region(iobase, EWRK3_TOTAL_SIZE);		}	} out:	return ret;}/*   ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually   ** the motherboard. */static int __init eisa_probe(struct net_device *dev, u_long ioaddr){	int i, maxSlots;	u_long iobase;	int ret = -ENODEV;	if (ioaddr < 0x1000)		goto out;	iobase = ioaddr;	i = (ioaddr >> 12);	maxSlots = i + 1;	for (i = 1; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) {		if (EISA_signature(name, EISA_ID) == 0) {			if (request_region(iobase, EWRK3_TOTAL_SIZE, DRV_NAME) &&			    DevicePresent(iobase) == 0) {				int irq = dev->irq;				ret = ewrk3_hw_init(dev, iobase);				if (!ret)					break;				dev->irq = irq;			}			release_region(iobase, EWRK3_TOTAL_SIZE);		}	} out:	return ret;}/*   ** 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. */static void __init EthwrkSignature(char *name, char *eeprom_image){	int i;	char *signatures[] = EWRK3_SIGNATURE;	for (i=0; *signatures[i] != '\0'; i++)		if( !strncmp(eeprom_image+EEPROM_PNAME7, signatures[i], strlen(signatures[i])) )			break;	if (*signatures[i] != '\0') {		memcpy(name, eeprom_image+EEPROM_PNAME7, EWRK3_STRLEN);		name[EWRK3_STRLEN] = '\0';	} else		name[0] = '\0';	return;}/*   ** 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. */static int __init 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;}static u_char __init get_hw_addr(struct net_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 */static int __init 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);	}

⌨️ 快捷键说明

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