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

📄 eepro.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			if (inb(ioaddr + STATUS_REG) & 0x08)			{				i = inb(ioaddr);				outb(0x08, ioaddr + STATUS_REG);				if (i & 0x20) { /* command ABORTed */					printk(KERN_NOTICE "%s: multicast setup failed.\n",						dev->name);					break;				} else if ((i & 0x0f) == 0x03)	{ /* MC-Done */					printk(KERN_DEBUG "%s: set Rx mode to %d address%s.\n",						dev->name, dev->mc_count,						dev->mc_count > 1 ? "es":"");					break;				}			}		} while (++boguscount < 100);		/* Re-enable RX and TX interrupts */		eepro_en_int(ioaddr);	}	if (lp->eepro == LAN595FX_10ISA) {		eepro_complete_selreset(ioaddr);	}	else		eepro_en_rx(ioaddr);}/* The horrible routine to read a word from the serial EEPROM. *//* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read *//* The delay between EEPROM clock transitions. */#define eeprom_delay() { udelay(40); }#define EE_READ_CMD (6 << 6)intread_eeprom(int ioaddr, int location, struct net_device *dev){	int i;	unsigned short retval = 0;	struct eepro_local *lp = netdev_priv(dev);	short ee_addr = ioaddr + lp->eeprom_reg;	int read_cmd = location | EE_READ_CMD;	short ctrl_val = EECS ;	/* XXXX - black magic */		eepro_sw2bank1(ioaddr);		outb(0x00, ioaddr + STATUS_REG);	/* XXXX - black magic */	eepro_sw2bank2(ioaddr);	outb(ctrl_val, ee_addr);	/* Shift the read command bits out. */	for (i = 8; i >= 0; i--) {		short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI			: ctrl_val;		outb(outval, ee_addr);		outb(outval | EESK, ee_addr);	/* EEPROM clock tick. */		eeprom_delay();		outb(outval, ee_addr);	/* Finish EEPROM a clock tick. */		eeprom_delay();	}	outb(ctrl_val, ee_addr);	for (i = 16; i > 0; i--) {		outb(ctrl_val | EESK, ee_addr);	 eeprom_delay();		retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0);		outb(ctrl_val, ee_addr);  eeprom_delay();	}	/* Terminate the EEPROM access. */	ctrl_val &= ~EECS;	outb(ctrl_val | EESK, ee_addr);	eeprom_delay();	outb(ctrl_val, ee_addr);	eeprom_delay();	eepro_sw2bank0(ioaddr);	return retval;}static inthardware_send_packet(struct net_device *dev, void *buf, short length){	struct eepro_local *lp = netdev_priv(dev);	short ioaddr = dev->base_addr;	unsigned status, tx_available, last, end;	if (net_debug > 5)		printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name);		/* determine how much of the transmit buffer space is available */		if (lp->tx_end > lp->tx_start)		tx_available = lp->xmt_ram - (lp->tx_end - lp->tx_start);		else if (lp->tx_end < lp->tx_start)			tx_available = lp->tx_start - lp->tx_end;	else tx_available = lp->xmt_ram;	if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) >= tx_available) {		/* No space available ??? */		return 1;		}		last = lp->tx_end;		end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;	if (end >= lp->xmt_upper_limit + 2) { /* the transmit buffer is wrapped around */		if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) {				/* Arrrr!!!, must keep the xmt header together,				several days were lost to chase this one down. */			last = lp->xmt_lower_limit;				end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;			}		else end = lp->xmt_lower_limit + (end -						lp->xmt_upper_limit + 2);		}		outw(last, ioaddr + HOST_ADDRESS_REG);		outw(XMT_CMD, ioaddr + IO_PORT);		outw(0, ioaddr + IO_PORT);		outw(end, ioaddr + IO_PORT);		outw(length, ioaddr + IO_PORT);		if (lp->version == LAN595)			outsw(ioaddr + IO_PORT, buf, (length + 3) >> 1);		else {	/* LAN595TX or LAN595FX, capable of 32-bit I/O processing */			unsigned short temp = inb(ioaddr + INT_MASK_REG);			outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);			outsl(ioaddr + IO_PORT_32_BIT, buf, (length + 3) >> 2);			outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);		}		/* A dummy read to flush the DRAM write pipeline */		status = inw(ioaddr + IO_PORT);		if (lp->tx_start == lp->tx_end) {		outw(last, ioaddr + lp->xmt_bar);			outb(XMT_CMD, ioaddr);			lp->tx_start = last;   /* I don't like to change tx_start here */		}		else {			/* update the next address and the chain bit in the			last packet */			if (lp->tx_end != last) {				outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);				outw(last, ioaddr + IO_PORT);			}			outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);			status = inw(ioaddr + IO_PORT);			outw(status | CHAIN_BIT, ioaddr + IO_PORT);			/* Continue the transmit command */			outb(RESUME_XMT_CMD, ioaddr);		}		lp->tx_last = last;		lp->tx_end = end;		if (net_debug > 5)			printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);	return 0;}static voideepro_rx(struct net_device *dev){	struct eepro_local *lp = netdev_priv(dev);	short ioaddr = dev->base_addr;	short boguscount = 20;	short rcv_car = lp->rx_start;	unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size;	if (net_debug > 5)		printk(KERN_DEBUG "%s: entering eepro_rx routine.\n", dev->name);	/* Set the read pointer to the start of the RCV */	outw(rcv_car, ioaddr + HOST_ADDRESS_REG);	rcv_event = inw(ioaddr + IO_PORT);	while (rcv_event == RCV_DONE) {		rcv_status = inw(ioaddr + IO_PORT);		rcv_next_frame = inw(ioaddr + IO_PORT);		rcv_size = inw(ioaddr + IO_PORT);		if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) {			/* Malloc up new buffer. */			struct sk_buff *skb;			dev->stats.rx_bytes+=rcv_size;			rcv_size &= 0x3fff;			skb = dev_alloc_skb(rcv_size+5);			if (skb == NULL) {				printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);				dev->stats.rx_dropped++;				rcv_car = lp->rx_start + RCV_HEADER + rcv_size;				lp->rx_start = rcv_next_frame;				outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);				break;			}			skb_reserve(skb,2);			if (lp->version == LAN595)				insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1);			else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */				unsigned short temp = inb(ioaddr + INT_MASK_REG);				outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);				insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size),					(rcv_size + 3) >> 2);				outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);			}			skb->protocol = eth_type_trans(skb,dev);			netif_rx(skb);			dev->last_rx = jiffies;			dev->stats.rx_packets++;		}		else { /* Not sure will ever reach here,			I set the 595 to discard bad received frames */			dev->stats.rx_errors++;			if (rcv_status & 0x0100)				dev->stats.rx_over_errors++;			else if (rcv_status & 0x0400)				dev->stats.rx_frame_errors++;			else if (rcv_status & 0x0800)				dev->stats.rx_crc_errors++;			printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n",				dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);		}		if (rcv_status & 0x1000)			dev->stats.rx_length_errors++;		rcv_car = lp->rx_start + RCV_HEADER + rcv_size;		lp->rx_start = rcv_next_frame;		if (--boguscount == 0)			break;		outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);		rcv_event = inw(ioaddr + IO_PORT);	}	if (rcv_car == 0)		rcv_car = lp->rcv_upper_limit | 0xff;	outw(rcv_car - 1, ioaddr + RCV_STOP);	if (net_debug > 5)		printk(KERN_DEBUG "%s: exiting eepro_rx routine.\n", dev->name);}static voideepro_transmit_interrupt(struct net_device *dev){	struct eepro_local *lp = netdev_priv(dev);	short ioaddr = dev->base_addr;	short boguscount = 25;	short xmt_status;	while ((lp->tx_start != lp->tx_end) && boguscount--) {		outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);		xmt_status = inw(ioaddr+IO_PORT);		if (!(xmt_status & TX_DONE_BIT))				break;		xmt_status = inw(ioaddr+IO_PORT);		lp->tx_start = inw(ioaddr+IO_PORT);		netif_wake_queue (dev);		if (xmt_status & TX_OK)			dev->stats.tx_packets++;		else {			dev->stats.tx_errors++;			if (xmt_status & 0x0400) {				dev->stats.tx_carrier_errors++;				printk(KERN_DEBUG "%s: carrier error\n",					dev->name);				printk(KERN_DEBUG "%s: XMT status = %#x\n",					dev->name, xmt_status);			}			else {				printk(KERN_DEBUG "%s: XMT status = %#x\n",					dev->name, xmt_status);				printk(KERN_DEBUG "%s: XMT status = %#x\n",					dev->name, xmt_status);			}		}		if (xmt_status & 0x000f) {			dev->stats.collisions += (xmt_status & 0x000f);		}		if ((xmt_status & 0x0040) == 0x0) {			dev->stats.tx_heartbeat_errors++;		}	}}static int eepro_ethtool_get_settings(struct net_device *dev,					struct ethtool_cmd *cmd){	struct eepro_local	*lp = (struct eepro_local *)dev->priv;	cmd->supported = 	SUPPORTED_10baseT_Half |				SUPPORTED_10baseT_Full |				SUPPORTED_Autoneg;	cmd->advertising =	ADVERTISED_10baseT_Half |				ADVERTISED_10baseT_Full |				ADVERTISED_Autoneg;	if (GetBit(lp->word[5], ee_PortTPE)) {		cmd->supported |= SUPPORTED_TP;		cmd->advertising |= ADVERTISED_TP;	}	if (GetBit(lp->word[5], ee_PortBNC)) {		cmd->supported |= SUPPORTED_BNC;		cmd->advertising |= ADVERTISED_BNC;	}	if (GetBit(lp->word[5], ee_PortAUI)) {		cmd->supported |= SUPPORTED_AUI;		cmd->advertising |= ADVERTISED_AUI;	}	cmd->speed = SPEED_10;	if (dev->if_port == TPE && lp->word[1] & ee_Duplex) {		cmd->duplex = DUPLEX_FULL;	}	else {		cmd->duplex = DUPLEX_HALF;	}	cmd->port = dev->if_port;	cmd->phy_address = dev->base_addr;	cmd->transceiver = XCVR_INTERNAL;	if (lp->word[0] & ee_AutoNeg) {		cmd->autoneg = 1;	}	return 0;}static void eepro_ethtool_get_drvinfo(struct net_device *dev,					struct ethtool_drvinfo *drvinfo){	strcpy(drvinfo->driver, DRV_NAME);	strcpy(drvinfo->version, DRV_VERSION);	sprintf(drvinfo->bus_info, "ISA 0x%lx", dev->base_addr);}static const struct ethtool_ops eepro_ethtool_ops = {	.get_settings	= eepro_ethtool_get_settings,	.get_drvinfo 	= eepro_ethtool_get_drvinfo,};#ifdef MODULE#define MAX_EEPRO 8static struct net_device *dev_eepro[MAX_EEPRO];static int io[MAX_EEPRO] = {  [0 ... MAX_EEPRO-1] = -1};static int irq[MAX_EEPRO];static int mem[MAX_EEPRO] = {	/* Size of the rx buffer in KB */  [0 ... MAX_EEPRO-1] = RCV_DEFAULT_RAM/1024};static int autodetect;static int n_eepro;/* For linux 2.1.xx */MODULE_AUTHOR("Pascal Dupuis and others");MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver");MODULE_LICENSE("GPL");module_param_array(io, int, NULL, 0);module_param_array(irq, int, NULL, 0);module_param_array(mem, int, NULL, 0);module_param(autodetect, int, 0);MODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base addres(es)");MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)");MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)");MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)");int __init init_module(void){	struct net_device *dev;	int i;	if (io[0] == -1 && autodetect == 0) {		printk(KERN_WARNING "eepro_init_module: Probe is very dangerous in ISA boards!\n");		printk(KERN_WARNING "eepro_init_module: Please add \"autodetect=1\" to force probe\n");		return -ENODEV;	}	else if (autodetect) {		/* if autodetect is set then we must force detection */		for (i = 0; i < MAX_EEPRO; i++) {			io[i] = 0;		}		printk(KERN_INFO "eepro_init_module: Auto-detecting boards (May God protect us...)\n");	}	for (i = 0; io[i] != -1 && i < MAX_EEPRO; i++) {		dev = alloc_etherdev(sizeof(struct eepro_local));		if (!dev)			break;		dev->mem_end = mem[i];		dev->base_addr = io[i];		dev->irq = irq[i];		if (do_eepro_probe(dev) == 0) {			dev_eepro[n_eepro++] = dev;			continue;		}		free_netdev(dev);		break;	}	if (n_eepro)		printk(KERN_INFO "%s", version);	return n_eepro ? 0 : -ENODEV;}void __exitcleanup_module(void){	int i;	for (i=0; i<n_eepro; i++) {		struct net_device *dev = dev_eepro[i];		unregister_netdev(dev);		release_region(dev->base_addr, EEPRO_IO_EXTENT);		free_netdev(dev);	}}#endif /* MODULE */

⌨️ 快捷键说明

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