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

📄 ewrk3.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
				outb(page, EWRK3_IOPR);			} else if (lp->shmem_length == SHMEM_2K) {				buf = lp->shmem_base;				outb(page, EWRK3_MPR);			} else if (lp->shmem_length == SHMEM_32K) {				buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);				outb((page >> 4), EWRK3_MPR);			} else if (lp->shmem_length == SHMEM_64K) {				buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);				outb((page >> 5), EWRK3_MPR);			} else {				status = -1;				printk("%s: Oops - your private data area is hosed!\n", dev->name);			}			if (!status) {				char rx_status;				int pkt_len;				if (lp->shmem_length == IO_ONLY) {					rx_status = inb(EWRK3_DATA);					pkt_len = inb(EWRK3_DATA);					pkt_len |= ((u_short) inb(EWRK3_DATA) << 8);				} else {					rx_status = readb(buf);					buf += 1;					pkt_len = readw(buf);					buf += 3;				}				if (!(rx_status & R_ROK)) {	/* There was an error. */					lp->stats.rx_errors++;	/* Update the error stats. */					if (rx_status & R_DBE)						lp->stats.rx_frame_errors++;					if (rx_status & R_CRC)						lp->stats.rx_crc_errors++;					if (rx_status & R_PLL)						lp->stats.rx_fifo_errors++;				} else {					struct sk_buff *skb;					if ((skb = dev_alloc_skb(pkt_len + 2)) != NULL) {						unsigned char *p;						skb->dev = dev;						skb_reserve(skb, 2);	/* Align to 16 bytes */						p = skb_put(skb, pkt_len);						if (lp->shmem_length == IO_ONLY) {							*p = inb(EWRK3_DATA);	/* dummy read */							for (i = 0; i < pkt_len; i++) {								*p++ = inb(EWRK3_DATA);							}						} else {							memcpy_fromio(p, buf, pkt_len);						}						/*						   ** Notify the upper protocol layers that there is another						   ** packet to handle						 */						skb->protocol = eth_type_trans(skb, dev);						netif_rx(skb);						/*						   ** Update stats						 */						lp->stats.rx_packets++;						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 ((*(s32 *) & p[0] == -1) && (*(s16 *) & p[4] == -1)) {								lp->pktStats.broadcast++;							} else {								lp->pktStats.multicast++;							}						} else if ((*(s32 *) & p[0] == *(s32 *) & dev->dev_addr[0]) &&							   (*(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));						}					} else {						printk("%s: Insufficient memory; nuking packet.\n", dev->name);						lp->stats.rx_dropped++;		/* Really, deferred. */						break;					}				}			}			/*			   ** Return the received buffer to the free memory queue			 */			outb(page, EWRK3_FMQ);			if (tmpLock) {	/* If a lock was preempted */				if (lp->shmem_length == IO_ONLY) {	/* Replace old page */					outb(tmpPage, EWRK3_IOPR);				} else {					outb(tmpPage, EWRK3_MPR);				}			}			lp->lock = 0;	/* Unlock the page register */		} 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. */static int ewrk3_tx(struct device *dev){	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;	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) {				lp->stats.tx_errors++;				if (tx_status & T_NCL)					lp->stats.tx_carrier_errors++;				if (tx_status & T_LCL)					lp->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) {						lp->stats.collisions++;					} else {						lp->pktStats.excessive_collisions++;					}				}			} else {				lp->stats.tx_packets++;			}		}	}	return 0;}static int ewrk3_close(struct device *dev){	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;	u_long iobase = dev->base_addr;	u_char icr, csr;	dev->start = 0;	dev->tbusy = 1;	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);	}	MOD_DEC_USE_COUNT;	return 0;}static struct net_device_stats *ewrk3_get_stats(struct device *dev){	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;	/* Null body since there is no framing error counter */	return &lp->stats;}/*   ** Set or clear the multicast filter for this adapter. */static void set_multicast_list(struct device *dev){	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;	u_long iobase = dev->base_addr;	u_char csr;	csr = inb(EWRK3_CSR);	if (lp->shmem_length == IO_ONLY) {		lp->mctbl = (char *) PAGE0_HTE;	} else {		lp->mctbl = (char *) (lp->shmem_base + 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 device *dev){	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;	struct dev_mc_list *dmi = dev->mc_list;	u_long iobase = dev->base_addr;	int i;	char *addrs, j, bit, byte;	short *p = (short *) lp->mctbl;	u16 hashcode;	s32 crc, poly = CRC_POLYNOMIAL_LE;	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(EEPROM_OFFSET(lp->mctbl), 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, (char *) (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 = 0xffffffff;	/* init CRC for each address */				for (byte = 0; byte < ETH_ALEN; byte++) {	/* for each address byte */					/* process each address bit */					for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {						crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0);					}				}				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((short) ((long) lp->mctbl) + byte, EWRK3_PIR1);					tmp = inb(EWRK3_DATA);					tmp |= bit;					outw((short) ((long) lp->mctbl) + byte, EWRK3_PIR1);					outb(tmp, EWRK3_DATA);				} else {					writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte);				}			}		}	}	lp->lock = 0;		/* Unlock the page register */	return;}/*   ** ISA bus I/O device probe */__initfunc(static void isa_probe(struct device *dev, u_long ioaddr)){	int i = num_ewrk3s, maxSlots;	u_long iobase;	if (!ioaddr && autoprobed)		return;		/* Been here before ! */	if (ioaddr >= 0x400)		return;		/* Not ISA */	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 (!check_region(iobase, EWRK3_TOTAL_SIZE)) {			if (DevicePresent(iobase) == 0) {				if ((dev = alloc_device(dev, iobase)) != NULL) {					if (ewrk3_hw_init(dev, iobase) == 0) {						num_ewrk3s++;					}					num_eth++;				}			}		} else if (autoprobed) {			printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase);		}	}	return;}/*   ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually   ** the motherboard. */__initfunc(static void eisa_probe(struct device *dev, u_long ioaddr)){	int i, maxSlots;	u_long iobase;	char name[EWRK3_STRLEN];	if (!ioaddr && autoprobed)		return;		/* Been here before ! */	if (ioaddr < 0x1000)		return;		/* Not EISA */	if (ioaddr == 0) {	/* Autoprobing */		iobase = EISA_SLOT_INC;		/* Get the first slot address */		i = 1;		maxSlots = MAX_EISA_SLOTS;	} else {		/* Probe a specific location */		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 (!check_region(iobase, EWRK3_TOTAL_SIZE)) {				if (DevicePresent(iobase) == 0) {					if ((dev = alloc_device(dev, iobase)) != NULL) {						if (ewrk3_hw_init(dev, iobase) == 0) {							num_ewrk3s++;						}						num_eth++;					}				}			} else if (autoprobed) {				printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase);			}		}	}	return;}/*   ** Search the entire 'eth' device list for a fixed probe. If a match isn't   ** found then check for an autoprobe or unused device location. If they   ** are not available then insert a new device structure at the end of   ** the current list. */__initfunc(static struct device *	   alloc_device(struct device *dev, u_long iobase)){	struct device *adev = NULL;	int fixed = 0, new_dev = 0;	num_eth = ewrk3_dev_index(dev->name);	if (loading_module)		return dev;	while (1) {		if (((dev->base_addr == EWRK3_NDA) || (dev->base_addr == 0)) && !adev) {			adev = dev;		} else if ((dev->priv == NULL) && (dev->base_addr == iobase)) {			fixed = 1;		} else {			if (dev->next == NULL) {				new_dev = 1;			} else if (strncmp(dev->next->name, "eth", 3) != 0) {				new_dev = 1;			}		}		if ((dev->next == NULL) || new_dev || fixed)			break;		dev = dev->next;		num_eth++;	}	if (adev && !fixed) {		dev = adev;		num_eth = ewrk3_dev_index(dev->name);		new_dev = 0;	}	if (((dev->next == NULL) &&	     ((dev->base_addr != EWRK3_NDA) && (dev->base_addr != 0)) && !fixed) ||	    new_dev) {		num_eth++;	/* New device */		dev = insert_device(dev, iobase, ewrk3_probe);	}	return dev;}/*   ** If at end of eth device list and can't use current entry, malloc   ** one up. If memory could not be allocated, print an error message. */__initfunc(static struct device *	   insert_device(struct device *dev, u_long iobase, int (*init) (struct device *))){	struct device *new;	new = (struct device *) kmalloc(sizeof(struct device) + 8, GFP_KERNEL);	if (new == NULL) {		printk("eth%d: Device not initialised, insufficient memory\n", num_eth);		return NULL;	} else {		new->next = dev->next;		dev->next = new;		dev = dev->next;	/* point to the new device */		dev->name = (char *) (dev + 1);		if (num_eth > 9999) {			sprintf(dev->name, "eth????");	/* New device name */		} else {			sprintf(dev->name, "eth%d", num_eth);	/* New device name */		}		dev->base_addr = iobase;	/* assign the io address */		dev->init = init;	/* initialisation routine */	}	return dev;}__initfunc(static int

⌨️ 快捷键说明

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