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

📄 at1700.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
📖 第 1 页 / 共 2 页
字号:
static int net_open(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	int ioaddr = dev->base_addr;	int i;	/* Powerup the chip, initialize config register 1, and select bank 0. */	outb(0xe0, ioaddr + CONFIG_1);	/* Set the station address in bank zero. */	for (i = 0; i < 6; i++)		outb(dev->dev_addr[i], ioaddr + 8 + i);	/* Switch to bank 1 and set the multicast table to accept none. */	outb(0xe4, ioaddr + 7);	for (i = 0; i < 8; i++)		outb(0x00, ioaddr + 8 + i);	/* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit	   bus access, and two 4K Tx queues. */	outb(0xda, ioaddr + CONFIG_0);	/* Same config 0, except enable the Rx and Tx. */	outb(0x5a, ioaddr + CONFIG_0);	/* Switch to register bank 2 for the run-time registers. */	outb(0xe8, ioaddr + CONFIG_1);	/* Turn on Rx interrupts, leave Tx interrupts off until packet Tx. */	outb(0x00, ioaddr + TX_INTR);	outb(0x81, ioaddr + RX_INTR);	lp->open_time = jiffies;	dev->tbusy = 0;	dev->interrupt = 0;	dev->start = 1;	return 0;}static intnet_send_packet(struct sk_buff *skb, struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	int ioaddr = dev->base_addr;	if (dev->tbusy) {		/* If we get here, some higher level has decided we are broken.		   There should really be a "kick me" function call instead. */		int tickssofar = jiffies - dev->trans_start;		if (tickssofar < 10)			return 1;		printk("%s: transmit timed out with status %04x, %s?\n", dev->name,			   inw(ioaddr + STATUS), inb(ioaddr + TX_STATUS) & 0x80			   ? "IRQ conflict" : "network cable problem");		printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",			   dev->name, inw(ioaddr + 0), inw(ioaddr + 2), inw(ioaddr + 4),			   inw(ioaddr + 6), inw(ioaddr + 8), inw(ioaddr + 10),			   inw(ioaddr + 12), inw(ioaddr + 14));		lp->stats.tx_errors++;		/* ToDo: We should try to restart the adaptor... */		outw(0xffff, ioaddr + 24);		outw(0xffff, ioaddr + TX_STATUS);		outw(0xe85a, ioaddr + CONFIG_0);		outw(0x8100, ioaddr + TX_INTR);		dev->tbusy=0;		dev->trans_start = jiffies;	}	/* If some higher layer thinks we've missed an tx-done interrupt	   we are passed NULL. Caution: dev_tint() handles the cli()/sti()	   itself. */	if (skb == NULL) {		dev_tint(dev);		return 0;	}	/* For ethernet, fill in the header.  This should really be done by a	   higher level, rather than duplicated for each ethernet adaptor. */	if (!skb->arp  &&  dev->rebuild_header(skb->data, dev)) {		skb->dev = dev;		arp_queue (skb);		return 0;	}	skb->arp=1;	/* Block a timer-based transmit from overlapping.  This could better be	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */	if (set_bit(0, (void*)&dev->tbusy) != 0)		printk("%s: Transmitter access conflict.\n", dev->name);	else {		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;		unsigned char *buf = skb->data;		/* Turn off the possible Tx interrupts. */		outb(0x00, ioaddr + TX_INTR);				outw(length, ioaddr + DATAPORT);		outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);		lp->tx_queue++;		lp->tx_queue_len += length + 2;		if (lp->tx_started == 0) {			/* If the Tx is idle, always trigger a transmit. */			outb(0x80 | lp->tx_queue, ioaddr + TX_START);			lp->tx_queue = 0;			lp->tx_queue_len = 0;			dev->trans_start = jiffies;			lp->tx_started = 1;		} else if (lp->tx_queue_len < 4096 - 1502)	/* Room for one more packet? */			dev->tbusy = 0;		/* Turn on Tx interrupts back on. */		outb(0x82, ioaddr + TX_INTR);	}	if (skb->free)		kfree_skb (skb, FREE_WRITE);	return 0;}/* The typical workload of the driver:   Handle the network interface interrupts. */static voidnet_interrupt(int reg_ptr){	int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);	struct device *dev = (struct device *)(irq2dev_map[irq]);	struct net_local *lp;	int ioaddr, status;	if (dev == NULL) {		printk ("at1700_interrupt(): irq %d for unknown device.\n", irq);		return;	}	dev->interrupt = 1;	ioaddr = dev->base_addr;	lp = (struct net_local *)dev->priv;	status = inw(ioaddr + TX_STATUS);	outw(status, ioaddr + TX_STATUS);	if (net_debug > 4)		printk("%s: Interrupt with status %04x.\n", dev->name, status);	if (status & 0xff00		||  (inb(ioaddr + RX_MODE) & 0x40) == 0) {			/* Got a packet(s). */		net_rx(dev);	}	if (status & 0x00ff) {		if (status & 0x80) {			lp->stats.tx_packets++;			if (lp->tx_queue) {				outb(0x80 | lp->tx_queue, ioaddr + TX_START);				lp->tx_queue = 0;				lp->tx_queue_len = 0;				dev->trans_start = jiffies;				dev->tbusy = 0;				mark_bh(INET_BH);	/* Inform upper layers. */			} else {				lp->tx_started = 0;				/* Turn on Tx interrupts off. */				outb(0x00, ioaddr + TX_INTR);				dev->tbusy = 0;			}		}	}	return;}/* We have a good packet(s), get it/them out of the buffers. */static voidnet_rx(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	int ioaddr = dev->base_addr;	int boguscount = 5;	while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {		ushort status = inw(ioaddr + DATAPORT);		if (net_debug > 4)			printk("%s: Rxing packet mode %02x status %04x.\n",				   dev->name, inb(ioaddr + RX_MODE), status);#ifndef final_version		if (status == 0) {			outb(0x05, ioaddr + 14);			break;		}#endif		if ((status & 0xF0) != 0x20) {	/* There was an error. */			lp->stats.rx_errors++;			if (status & 0x08) lp->stats.rx_length_errors++;			if (status & 0x04) lp->stats.rx_frame_errors++;			if (status & 0x02) lp->stats.rx_crc_errors++;			if (status & 0x01) lp->stats.rx_over_errors++;		} else {			ushort pkt_len = inw(ioaddr + DATAPORT);			/* Malloc up new buffer. */			int sksize = sizeof(struct sk_buff) + pkt_len;			struct sk_buff *skb;			if (pkt_len > 1550) {				printk("%s: The AT1700 claimed a very large packet, size %d.\n",					   dev->name, pkt_len);				outb(0x05, ioaddr + 14);				lp->stats.rx_errors++;				break;			}			skb = alloc_skb(sksize, GFP_ATOMIC);			if (skb == NULL) {				printk("%s: Memory squeeze, dropping packet (len %d).\n",					   dev->name, pkt_len);				outb(0x05, ioaddr + 14);				lp->stats.rx_dropped++;				break;			}			skb->mem_len = sksize;			skb->mem_addr = skb;			skb->len = pkt_len;			skb->dev = dev;			insw(ioaddr + DATAPORT, skb->data, (pkt_len + 1) >> 1);			if (net_debug > 5) {				int i;				printk("%s: Rxed packet of length %d: ", dev->name, pkt_len);				for (i = 0; i < 14; i++)					printk(" %02x", skb->data[i]);				printk(".\n");			}#ifdef HAVE_NETIF_RX			netif_rx(skb);#else			skb->lock = 0;			if (dev_rint((unsigned char*)skb, pkt_len, IN_SKBUFF, dev) != 0) {				kfree_s(skb, sksize);				lp->stats.rx_dropped++;				break;			}#endif			lp->stats.rx_packets++;		}		if (--boguscount <= 0)			break;	}	/* If any worth-while packets have been received, dev_rint()	   has done a mark_bh(INET_BH) for us and will work on them	   when we get to the bottom-half routine. */	{		int i;		for (i = 0; i < 20; i++) {			if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)				break;			outb(0x05, ioaddr + 14);		}		if (net_debug > 5)			printk("%s: Exint Rx packet with mode %02x after %d ticks.\n", 				   dev->name, inb(ioaddr + RX_MODE), i);	}	return;}/* The inverse routine to net_open(). */static int net_close(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	int ioaddr = dev->base_addr;	lp->open_time = 0;	dev->tbusy = 1;	dev->start = 0;	/* Set configuration register 0 to disable Tx and Rx. */	outb(0xda, ioaddr + CONFIG_0);	/* Update the statistics -- ToDo. */	/* Power-down the chip.  Green, green, green! */	outb(0x00, ioaddr + CONFIG_1);	return 0;}/* Get the current statistics.	This may be called with the card open or   closed. */static struct enet_statistics *net_get_stats(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	cli();	/* ToDo: Update the statistics from the device registers. */	sti();	return &lp->stats;}#ifdef HAVE_MULTICAST/* Set or clear the multicast filter for this adaptor.   num_addrs == -1	Promiscuous mode, receive all packets   num_addrs == 0	Normal mode, clear multicast list   num_addrs > 0	Multicast mode, receive normal and MC packets, and do			best-effort filtering. */static voidset_multicast_list(struct device *dev, int num_addrs, void *addrs){	short ioaddr = dev->base_addr;	if (num_addrs) {		outw(3, ioaddr + RX_MODE);	/* Enable promiscuous mode */	} else		outw(2, ioaddr + RX_MODE);	/* Disable promiscuous, use normal mode */}#endif/* * Local variables: *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c at1700.c" *  version-control: t *  kept-new-versions: 5 *  tab-width: 4 * End: */

⌨️ 快捷键说明

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