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

📄 de620.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		dev->name,		"network cable problem"		);	/* Restart the adapter. */	if (!adapter_init(dev)) /* maybe close it */		netif_wake_queue(dev);}/******************************************************* * * Copy a buffer to the adapter transmit page memory. * Start sending. */static int de620_start_xmit(struct sk_buff *skb, struct net_device *dev){	unsigned long flags;	int len;	byte *buffer = skb->data;	byte using_txbuf;	using_txbuf = de620_tx_buffs(dev); /* Peek at the adapter */		netif_stop_queue(dev);		if ((len = skb->len) < RUNT)		len = RUNT;	if (len & 1) /* send an even number of bytes */		++len;	/* Start real output */	save_flags(flags);	cli();	PRINTK(("de620_start_xmit: len=%d, bufs 0x%02x\n",		(int)skb->len, using_txbuf));	/* select a free tx buffer. if there is one... */	switch (using_txbuf) {	default: /* both are free: use TXBF0 */	case TXBF1: /* use TXBF0 */		de620_send_command(dev,W_CR | RW0);		using_txbuf |= TXBF0;		break;	case TXBF0: /* use TXBF1 */		de620_send_command(dev,W_CR | RW1);		using_txbuf |= TXBF1;		break;	case (TXBF0 | TXBF1): /* NONE!!! */		printk(KERN_WARNING "%s: No tx-buffer available!\n", dev->name);		restore_flags(flags);		return 1;		break;	}	de620_write_block(dev, buffer, len);	dev->trans_start = jiffies;	if(!(using_txbuf == (TXBF0 | TXBF1)))		netif_wake_queue(dev);	((struct net_device_stats *)(dev->priv))->tx_packets++;	restore_flags(flags); /* interrupts maybe back on */	dev_kfree_skb (skb);	return 0;}/***************************************************** * * Handle the network interface interrupts. * */static void de620_interrupt(int irq_in, void *dev_id, struct pt_regs *regs){	struct net_device *dev = dev_id;	byte irq_status;	int bogus_count = 0;	int again = 0;	/* This might be deleted now, no crummy drivers present :-) Or..? */	if ((dev == NULL) || (irq != irq_in)) {		printk("%s: bogus interrupt %d\n", dev?dev->name:"de620", irq_in);		return;	}	/* Read the status register (_not_ the status port) */	irq_status = de620_get_register(dev, R_STS);	PRINTK(("de620_interrupt (%2.2X)\n", irq_status));	if (irq_status & RXGOOD) {		do {			again = de620_rx_intr(dev);			PRINTK(("again=%d\n", again));		}		while (again && (++bogus_count < 100));	}	if(de620_tx_buffs(dev) != (TXBF0 | TXBF1))		netif_wake_queue(dev);}/************************************** * * Get a packet from the adapter * * Send it "upstairs" * */static int de620_rx_intr(struct net_device *dev){	struct header_buf {		byte		status;		byte		Rx_NextPage;		unsigned short	Rx_ByteCount;	} header_buf;	struct sk_buff *skb;	int size;	byte *buffer;	byte pagelink;	byte curr_page;	PRINTK(("de620_rx_intr: next_rx_page = %d\n", next_rx_page));	/* Tell the adapter that we are going to read data, and from where */	de620_send_command(dev, W_CR | RRN);	de620_set_register(dev, W_RSA1, next_rx_page);	de620_set_register(dev, W_RSA0, 0);	/* Deep breath, and away we goooooo */	de620_read_block(dev, (byte *)&header_buf, sizeof(struct header_buf));	PRINTK(("page status=0x%02x, nextpage=%d, packetsize=%d\n",	header_buf.status, header_buf.Rx_NextPage, header_buf.Rx_ByteCount));	/* Plausible page header? */	pagelink = header_buf.Rx_NextPage;	if ((pagelink < first_rx_page) || (last_rx_page < pagelink)) {		/* Ouch... Forget it! Skip all and start afresh... */		printk(KERN_WARNING "%s: Ring overrun? Restoring...\n", dev->name);		/* You win some, you lose some. And sometimes plenty... */		adapter_init(dev);		netif_wake_queue(dev);		((struct net_device_stats *)(dev->priv))->rx_over_errors++;		return 0;	}	/* OK, this look good, so far. Let's see if it's consistent... */	/* Let's compute the start of the next packet, based on where we are */	pagelink = next_rx_page +		((header_buf.Rx_ByteCount + (4 - 1 + 0x100)) >> 8);	/* Are we going to wrap around the page counter? */	if (pagelink > last_rx_page)		pagelink -= (last_rx_page - first_rx_page + 1);	/* Is the _computed_ next page number equal to what the adapter says? */	if (pagelink != header_buf.Rx_NextPage) {		/* Naah, we'll skip this packet. Probably bogus data as well */		printk(KERN_WARNING "%s: Page link out of sync! Restoring...\n", dev->name);		next_rx_page = header_buf.Rx_NextPage; /* at least a try... */		de620_send_command(dev, W_DUMMY);		de620_set_register(dev, W_NPRF, next_rx_page);		((struct net_device_stats *)(dev->priv))->rx_over_errors++;		return 0;	}	next_rx_page = pagelink;	size = header_buf.Rx_ByteCount - 4;	if ((size < RUNT) || (GIANT < size)) {		printk(KERN_WARNING "%s: Illegal packet size: %d!\n", dev->name, size);	}	else { /* Good packet? */		skb = dev_alloc_skb(size+2);		if (skb == NULL) { /* Yeah, but no place to put it... */			printk(KERN_WARNING "%s: Couldn't allocate a sk_buff of size %d.\n",				dev->name, size);			((struct net_device_stats *)(dev->priv))->rx_dropped++;		}		else { /* Yep! Go get it! */			skb_reserve(skb,2);	/* Align */			skb->dev = dev;			skb->used = 0;			/* skb->data points to the start of sk_buff data area */			buffer = skb_put(skb,size);			/* copy the packet into the buffer */			de620_read_block(dev, buffer, size);			PRINTK(("Read %d bytes\n", size));			skb->protocol=eth_type_trans(skb,dev);			netif_rx(skb); /* deliver it "upstairs" */			/* count all receives */			((struct net_device_stats *)(dev->priv))->rx_packets++;		}	}	/* Let's peek ahead to see if we have read the last current packet */	/* NOTE! We're _not_ checking the 'EMPTY'-flag! This seems better... */	curr_page = de620_get_register(dev, R_CPR);	de620_set_register(dev, W_NPRF, next_rx_page);	PRINTK(("next_rx_page=%d CPR=%d\n", next_rx_page, curr_page));	return (next_rx_page != curr_page); /* That was slightly tricky... */}/********************************************* * * Reset the adapter to a known state * */static int adapter_init(struct net_device *dev){	int i;	static int was_down = 0;	if ((nic_data.Model == 3) || (nic_data.Model == 0)) { /* CT */		EIPRegister = NCTL0;		if (nic_data.Media != 1)			EIPRegister |= NIS0;	/* not BNC */	}	else if (nic_data.Model == 2) { /* UTP */		EIPRegister = NCTL0 | NIS0;	}	if (utp)		EIPRegister = NCTL0 | NIS0;	if (bnc)		EIPRegister = NCTL0;	de620_send_command(dev, W_CR | RNOP | CLEAR);	de620_send_command(dev, W_CR | RNOP);	de620_set_register(dev, W_SCR, SCR_DEF);	/* disable recv to wait init */	de620_set_register(dev, W_TCR, RXOFF);	/* Set the node ID in the adapter */	for (i = 0; i < 6; ++i) { /* W_PARn = 0xaa + n */		de620_set_register(dev, W_PAR0 + i, dev->dev_addr[i]);	}	de620_set_register(dev, W_EIP, EIPRegister);	next_rx_page = first_rx_page = DE620_RX_START_PAGE;	if (nic_data.RAM_Size)		last_rx_page = nic_data.RAM_Size - 1;	else /* 64k RAM */		last_rx_page = 255;	de620_set_register(dev, W_SPR, first_rx_page); /* Start Page Register*/	de620_set_register(dev, W_EPR, last_rx_page);  /* End Page Register */	de620_set_register(dev, W_CPR, first_rx_page);/*Current Page Register*/	de620_send_command(dev, W_NPR | first_rx_page); /* Next Page Register*/	de620_send_command(dev, W_DUMMY);	de620_set_delay(dev);	/* Final sanity check: Anybody out there? */	/* Let's hope some bits from the statusregister make a good check */#define CHECK_MASK (  0 | TXSUC |  T16  |  0  | RXCRC | RXSHORT |  0  |  0  )#define CHECK_OK   (  0 |   0   |  0    |  0  |   0   |   0     |  0  |  0  )        /* success:   X     0      0       X      0       0        X     X  */        /* ignore:   EEDI                RXGOOD                   COLS  LNKS*/	if (((i = de620_get_register(dev, R_STS)) & CHECK_MASK) != CHECK_OK) {		printk(KERN_ERR "%s: Something has happened to the DE-620!  Please check it"#ifdef SHUTDOWN_WHEN_LOST			" and do a new ifconfig"#endif			"! (%02x)\n", dev->name, i);#ifdef SHUTDOWN_WHEN_LOST		/* Goodbye, cruel world... */		dev->flags &= ~IFF_UP;		de620_close(dev);#endif		was_down = 1;		return 1; /* failed */	}	if (was_down) {		printk(KERN_WARNING "%s: Thanks, I feel much better now!\n", dev->name);		was_down = 0;	}	/* All OK, go ahead... */	de620_set_register(dev, W_TCR, TCR_DEF);	return 0; /* all ok */}/****************************************************************************** * * Only start-up code below * *//**************************************** * * Check if there is a DE-620 connected */int __init de620_probe(struct net_device *dev){	static struct net_device_stats de620_netstats;	int i;	byte checkbyte = 0xa5;	SET_MODULE_OWNER(dev);	/*	 * This is where the base_addr and irq gets set.	 * Tunable at compile-time and insmod-time	 */	dev->base_addr = io;	dev->irq       = irq;	if (de620_debug)		printk(version);	printk(KERN_INFO "D-Link DE-620 pocket adapter");	/* Initially, configure basic nibble mode, so we can read the EEPROM */	NIC_Cmd = DEF_NIC_CMD;	de620_set_register(dev, W_EIP, EIPRegister);	/* Anybody out there? */	de620_set_register(dev, W_CPR, checkbyte);	checkbyte = de620_get_register(dev, R_CPR);	if ((checkbyte != 0xa5) || (read_eeprom(dev) != 0)) {		printk(" not identified in the printer port\n");		return -ENODEV;	}#if 0 /* Not yet */	if (check_region(dev->base_addr, 3)) {		printk(", port 0x%x busy\n", dev->base_addr);		return -EBUSY;	}#endif	request_region(dev->base_addr, 3, "de620");	/* else, got it! */	printk(", Ethernet Address: %2.2X",		dev->dev_addr[0] = nic_data.NodeID[0]);	for (i = 1; i < ETH_ALEN; i++) {		printk(":%2.2X", dev->dev_addr[i] = nic_data.NodeID[i]);		dev->broadcast[i] = 0xff;	}	printk(" (%dk RAM,",		(nic_data.RAM_Size) ? (nic_data.RAM_Size >> 2) : 64);	if (nic_data.Media == 1)		printk(" BNC)\n");	else		printk(" UTP)\n");	/* Initialize the device structure. */	dev->priv = &de620_netstats;	memset(dev->priv, 0, sizeof(struct net_device_stats));	dev->get_stats 		= get_stats;	dev->open 		= de620_open;	dev->stop 		= de620_close;	dev->hard_start_xmit 	= de620_start_xmit;	dev->tx_timeout 	= de620_timeout;	dev->watchdog_timeo	= HZ*2;	dev->set_multicast_list = de620_set_multicast_list;		/* base_addr and irq are already set, see above! */	ether_setup(dev);	/* dump eeprom */	if (de620_debug) {		printk("\nEEPROM contents:\n");		printk("RAM_Size = 0x%02X\n", nic_data.RAM_Size);		printk("NodeID = %02X:%02X:%02X:%02X:%02X:%02X\n",			nic_data.NodeID[0], nic_data.NodeID[1],			nic_data.NodeID[2], nic_data.NodeID[3],			nic_data.NodeID[4], nic_data.NodeID[5]);		printk("Model = %d\n", nic_data.Model);		printk("Media = %d\n", nic_data.Media);		printk("SCR = 0x%02x\n", nic_data.SCR);	}	return 0;}/********************************** * * Read info from on-board EEPROM * * Note: Bitwise serial I/O to/from the EEPROM vi the status _register_! */#define sendit(dev,data) de620_set_register(dev, W_EIP, data | EIPRegister);static unsigned short __init ReadAWord(struct net_device *dev, int from){	unsigned short data;	int nbits;	/* cs   [__~~] SET SEND STATE */	/* di   [____]                */	/* sck  [_~~_]                */	sendit(dev, 0); sendit(dev, 1); sendit(dev, 5); sendit(dev, 4);	/* Send the 9-bit address from where we want to read the 16-bit word */	for (nbits = 9; nbits > 0; --nbits, from <<= 1) {		if (from & 0x0100) { /* bit set? */			/* cs    [~~~~] SEND 1 */			/* di    [~~~~]        */			/* sck   [_~~_]        */			sendit(dev, 6); sendit(dev, 7); sendit(dev, 7); sendit(dev, 6);		}		else {			/* cs    [~~~~] SEND 0 */			/* di    [____]        */			/* sck   [_~~_]        */			sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4);		}	}	/* Shift in the 16-bit word. The bits appear serially in EEDI (=0x80) */	for (data = 0, nbits = 16; nbits > 0; --nbits) {		/* cs    [~~~~] SEND 0 */		/* di    [____]        */		/* sck   [_~~_]        */		sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4);		data = (data << 1) | ((de620_get_register(dev, R_STS) & EEDI) >> 7);	}	/* cs    [____] RESET SEND STATE */	/* di    [____]                  */	/* sck   [_~~_]                  */	sendit(dev, 0); sendit(dev, 1); sendit(dev, 1); sendit(dev, 0);	return data;}static int __init read_eeprom(struct net_device *dev){	unsigned short wrd;	/* D-Link Ethernet addresses are in the series  00:80:c8:7X:XX:XX:XX */	wrd = ReadAWord(dev, 0x1aa);	/* bytes 0 + 1 of NodeID */	if (!clone && (wrd != htons(0x0080))) /* Valid D-Link ether sequence? */		return -1; /* Nope, not a DE-620 */	nic_data.NodeID[0] = wrd & 0xff;	nic_data.NodeID[1] = wrd >> 8;	wrd = ReadAWord(dev, 0x1ab);	/* bytes 2 + 3 of NodeID */	if (!clone && ((wrd & 0xff) != 0xc8)) /* Valid D-Link ether sequence? */		return -1; /* Nope, not a DE-620 */	nic_data.NodeID[2] = wrd & 0xff;	nic_data.NodeID[3] = wrd >> 8;	wrd = ReadAWord(dev, 0x1ac);	/* bytes 4 + 5 of NodeID */	nic_data.NodeID[4] = wrd & 0xff;	nic_data.NodeID[5] = wrd >> 8;	wrd = ReadAWord(dev, 0x1ad);	/* RAM size in pages (256 bytes). 0 = 64k */	nic_data.RAM_Size = (wrd >> 8);	wrd = ReadAWord(dev, 0x1ae);	/* hardware model (CT = 3) */	nic_data.Model = (wrd & 0xff);	wrd = ReadAWord(dev, 0x1af); /* media (indicates BNC/UTP) */	nic_data.Media = (wrd & 0xff);	wrd = ReadAWord(dev, 0x1a8); /* System Configuration Register */	nic_data.SCR = (wrd >> 8);	return 0; /* no errors */}/****************************************************************************** * * Loadable module skeleton * */#ifdef MODULEstatic struct net_device de620_dev;int init_module(void){	de620_dev.init = de620_probe;	if (register_netdev(&de620_dev) != 0)		return -EIO;	return 0;}void cleanup_module(void){	unregister_netdev(&de620_dev);	release_region(de620_dev.base_addr, 3);}#endif /* MODULE *//* * (add '-DMODULE' when compiling as loadable module) * * compile-command: *	gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O2 \ *	 -fomit-frame-pointer -m486 \ *	-I/usr/src/linux/include -I../../net/inet -c de620.c*//* * Local variables: *  kernel-compile-command: "gcc -D__KERNEL__ -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c" *  module-compile-command: "gcc -D__KERNEL__ -DMODULE -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c" *  compile-command: "gcc -D__KERNEL__ -DMODULE -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c" * End: */

⌨️ 快捷键说明

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