亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? skeleton.c

?? 內核是系統(tǒng)的心臟
?? C
字號:
/* skeleton.c: A sample network driver core for linux. */
/*
	Written 1993 by Donald Becker.
	Copyright 1993 United States Government as represented by the Director,
	National Security Agency.  This software may only be used and distributed
	according to the terms of the GNU Public License as modified by SRC,
	incorporated herein by reference.

	The author may be reached as becker@super.org or
	C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715

	This file is an outline for writing a network device driver for the
	the Linux operating system.

	To write (or understand) a driver, have a look at the "loopback.c" file to
	get a feel of what is going on, and then use the code below as a skeleton
	for the new driver.

*/

static char *version =
	"skeleton.c:v0.05 11/16/93 Donald Becker (becker@super.org)\n";

/* Always include 'config.h' first in case the user wants to turn on
   or override something. */
#include <linux/config.h>

/*
  Sources:
	List your sources of programming information to document that
	the driver is your own creation, and give due credit to others
	that contributed to the work.  Remember that GNU project code
	cannot use proprietary or trade secret information.	 Interface
	definitions are generally considered non-copyrightable to the
	extent that the same names and structures must be used to be
	compatible.

	Finally, keep in mind that the Linux kernel is has an API, not
	ABI.  Proprietary object-code-only distributions are not permitted
	under the GPL.
*/

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/malloc.h>
#include <linux/string.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <errno.h>

#include "dev.h"
#include "eth.h"
#include "skbuff.h"
#include "arp.h"

#ifndef HAVE_AUTOIRQ
/* From auto_irq.c, in ioport.h for later versions. */
extern void autoirq_setup(int waittime);
extern int autoirq_report(int waittime);
/* The map from IRQ number (as passed to the interrupt handler) to
   'struct device'. */
extern struct device *irq2dev_map[16];
#endif

#ifndef HAVE_ALLOC_SKB
#define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority)
#define kfree_skbmem(addr, size) kfree_s(addr,size);
#endif

#ifndef HAVE_PORTRESERVE
#define check_region(ioaddr, size) 		0
#define	snarf_region(ioaddr, size);		do ; while (0)
#endif

/* use 0 for production, 1 for verification, >2 for debug */
#ifndef NET_DEBUG
#define NET_DEBUG 2
#endif
static unsigned int net_debug = NET_DEBUG;

/* Information that need to be kept for each board. */
struct net_local {
	struct enet_statistics stats;
	long open_time;				/* Useless example local info. */
};

/* The number of low I/O ports used by the ethercard. */
#define ETHERCARD_TOTAL_SIZE	16

/* The station (ethernet) address prefix, used for IDing the board. */
#define SA_ADDR0 0x00
#define SA_ADDR1 0x42
#define SA_ADDR2 0x65

/* Index to functions, as function prototypes. */

extern int netcard_probe(struct device *dev);

static int netcard_probe1(struct device *dev, short ioaddr);
static int net_open(struct device *dev);
static int	net_send_packet(struct sk_buff *skb, struct device *dev);
static void net_interrupt(int reg_ptr);
static void net_rx(struct device *dev);
static int net_close(struct device *dev);
static struct enet_statistics *net_get_stats(struct device *dev);
#ifdef HAVE_MULTICAST
static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
#endif

/* Example routines you must write ;->. */
#define tx_done(dev) 1
extern void	hardware_send_packet(short ioaddr, char *buf, int length);
extern void chipset_init(struct device *dev, int startp);


/* Check for a network adaptor of this type, and return '0' iff one exists.
   If dev->base_addr == 0, probe all likely locations.
   If dev->base_addr == 1, always return failure.
   If dev->base_addr == 2, alloate space for the device and return success
   (detachable devices only).
   */
int
netcard_probe(struct device *dev)
{
	int *port, ports[] = {0x300, 0x280, 0};
	int base_addr = dev->base_addr;

	if (base_addr > 0x1ff)		/* Check a single specified location. */
		return netcard_probe1(dev, base_addr);
	else if (base_addr > 0)		/* Don't probe at all. */
		return ENXIO;

	for (port = &ports[0]; *port; port++) {
		int ioaddr = *port;
		if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE))
			continue;
		if (inb(ioaddr) != 0x57)
			continue;
		dev->base_addr = ioaddr;
		if (netcard_probe1(dev, ioaddr) == 0)
			return 0;
	}

	dev->base_addr = base_addr;
	return ENODEV;
}

int netcard_probe1(struct device *dev, short ioaddr)
{
	unsigned char station_addr[6];
	int i;

	/* Read the station address PROM.  */
	for (i = 0; i < 6; i++) {
		station_addr[i] = inb(ioaddr + i);
	}
	/* Check the first three octets of the S.A. for the manufactor's code. */ 
	if (station_addr[0] != SA_ADDR0
		||	 station_addr[1] != SA_ADDR1 || station_addr[2] != SA_ADDR2) {
		return ENODEV;
	}

	printk("%s: %s found at %#3x, IRQ %d.\n", dev->name,
		   "network card", dev->base_addr, dev->irq);

#ifdef jumpered_interrupts
	/* If this board has jumpered interrupts, snarf the interrupt vector
	   now.	 There is no point in waiting since no other device can use
	   the interrupt, and this marks the 'irqaction' as busy. */

	if (dev->irq == -1)
		;			/* Do nothing: a user-level program will set it. */
	else if (dev->irq < 2) {	/* "Auto-IRQ" */
		autoirq_setup(0);
		/* Trigger an interrupt here. */

		dev->irq = autoirq_report(0);
		if (net_debug >= 2)
			printk(" autoirq is %d", dev->irq);
  } else if (dev->irq == 2)
	  /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
	 or don't know which one to set. */
	  dev->irq = 9;

	{	 int irqval = request_irq(dev->irq, &net_interrupt);
		 if (irqval) {
			 printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
					 dev->irq, irqval);
			 return EAGAIN;
		 }
	 }
#endif	/* jumpered interrupt */

	/* Grab the region so we can find another board if autoIRQ fails. */
	snarf_region(ioaddr, ETHERCARD_TOTAL_SIZE);

	if (net_debug)
		printk(version);

	/* Initialize the device structure. */
	dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
	memset(dev->priv, 0, sizeof(struct net_local));

	dev->open		= net_open;
	dev->stop		= net_close;
	dev->hard_start_xmit = net_send_packet;
	dev->get_stats	= net_get_stats;
#ifdef HAVE_MULTICAST
	dev->set_multicast_list = &set_multicast_list;
#endif

	/* Fill in the fields of the device structure with ethernet-generic values.
	   This should be in a common file instead of per-driver.  */
	for (i = 0; i < DEV_NUMBUFFS; i++)
		dev->buffs[i] = NULL;

	dev->hard_header	= eth_header;
	dev->add_arp		= eth_add_arp;
	dev->queue_xmit		= dev_queue_xmit;
	dev->rebuild_header	= eth_rebuild_header;
	dev->type_trans		= eth_type_trans;

	dev->type			= ARPHRD_ETHER;
	dev->hard_header_len = ETH_HLEN;
	dev->mtu			= 1500; /* eth_mtu */
	dev->addr_len		= ETH_ALEN;
	for (i = 0; i < ETH_ALEN; i++) {
		dev->broadcast[i]=0xff;
	}

	/* New-style flags. */
	dev->flags			= IFF_BROADCAST;
	dev->family			= AF_INET;
	dev->pa_addr		= 0;
	dev->pa_brdaddr		= 0;
	dev->pa_mask		= 0;
	dev->pa_alen		= sizeof(unsigned long);

	return 0;
}


/* Open/initialize the board.  This is called (in the current kernel)
   sometime after booting when the 'ifconfig' program is run.

   This routine should set everything up anew at each open, even
   registers that "should" only need to be set once at boot, so that
   there is non-reboot way to recover if something goes wrong.
   */
static int
net_open(struct device *dev)
{
	struct net_local *lp = (struct net_local *)dev->priv;
	int ioaddr = dev->base_addr;

	/* This is used if the interrupt line can turned off (shared).
	   See 3c503.c for an example of selecting the IRQ at config-time. */
	if (request_irq(dev->irq, &net_interrupt)) {
		return -EAGAIN;
	}


	/* Always snarf a DMA channel after the IRQ. */
	if (request_dma(dev->dma)) {
		free_irq(dev->irq);
		return -EAGAIN;
	}
	irq2dev_map[dev->irq] = dev;

	/* Reset the hardware here. */
	/*chipset_init(dev, 1);*/
	outb(0x00, ioaddr);
	lp->open_time = jiffies;

	dev->tbusy = 0;
	dev->interrupt = 0;
	dev->start = 1;
	return 0;
}

static int
net_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 < 5)
			return 1;
		printk("%s: transmit timed out, %s?\n", dev->name,
			   tx_done(dev) ? "IRQ conflict" : "network cable problem");
		/* Try to restart the adaptor. */
		chipset_init(dev, 1);
		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;

		hardware_send_packet(ioaddr, buf, length);
		dev->trans_start = jiffies;
	}
	if (skb->free)
		kfree_skb (skb, FREE_WRITE);

	/* You might need to clean up and record Tx statistics here. */
	if (inw(ioaddr) == /*RU*/81)
		lp->stats.tx_aborted_errors++;

	return 0;
}

/* The typical workload of the driver:
   Handle the network interface interrupts. */
static void
net_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, boguscount = 0;

	if (dev == NULL) {
		printk ("net_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 + 0);

	do {
		if (status /*& RX_INTR*/) {
			/* Got a packet(s). */
			net_rx(dev);
		}
		if (status /*& TX_INTR*/) {
			lp->stats.tx_packets++;
			dev->tbusy = 0;
			mark_bh(INET_BH);	/* Inform upper layers. */
		}
		if (status /*& COUNTERS_INTR*/) {
			/* Increment the appropriate 'localstats' field. */
			lp->stats.tx_window_errors++;
		}
	} while (++boguscount < 20) ;

	return;
}

/* We have a good packet(s), get it/them out of the buffers. */
static void
net_rx(struct device *dev)
{
	struct net_local *lp = (struct net_local *)dev->priv;
	int ioaddr = dev->base_addr;
	int boguscount = 10;

	do {
		int status = inw(ioaddr);
		int pkt_len = inw(ioaddr);
	  
		if (pkt_len == 0)		/* Read all the frames? */
			break;			/* Done for now */

		if (status & 0x40) {	/* There was an error. */
			lp->stats.rx_errors++;
			if (status & 0x20) lp->stats.rx_frame_errors++;
			if (status & 0x10) lp->stats.rx_over_errors++;
			if (status & 0x08) lp->stats.rx_crc_errors++;
			if (status & 0x04) lp->stats.rx_fifo_errors++;
		} else {
			/* Malloc up new buffer. */
			int sksize = sizeof(struct sk_buff) + pkt_len;
			struct sk_buff *skb;

			skb = alloc_skb(sksize, GFP_ATOMIC);
			if (skb == NULL) {
				printk("%s: Memory squeeze, dropping packet.\n", dev->name);
				lp->stats.rx_dropped++;
				break;
			}
			skb->mem_len = sksize;
			skb->mem_addr = skb;
			skb->len = pkt_len;
			skb->dev = dev;

			/* 'skb->data' points to the start of sk_buff data area. */
			memcpy(skb->data, (void*)dev->rmem_start,
				   pkt_len);
			/* or */
			insw(ioaddr, skb->data, (pkt_len + 1) >> 1);

#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++;
		}
	} while (--boguscount);

	/* 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. */
	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;

	/* Flush the Tx and disable Rx here. */

	disable_dma(dev->dma);

	/* If not IRQ or DMA jumpered, free up the line. */
	outw(0x00, ioaddr+0);		/* Release the physical interrupt line. */

	free_irq(dev->irq);
	free_dma(dev->dma);

	irq2dev_map[dev->irq] = 0;

	/* Update the statistics here. */

	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;
	short ioaddr = dev->base_addr;

	cli();
	/* Update the statistics from the device registers. */
	lp->stats.rx_missed_errors = inw(ioaddr+1);
	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 void
set_multicast_list(struct device *dev, int num_addrs, void *addrs)
{
	short ioaddr = dev->base_addr;
	if (num_addrs) {
		outw(69, ioaddr);		/* Enable promiscuous mode */
	} else
		outw(99, ioaddr);		/* Disable promiscuous mode, use normal mode */
}
#endif

/*
 * Local variables:
 *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c"
 *  version-control: t
 *  kept-new-versions: 5
 *  tab-width: 4
 * End:
 */

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
亚洲不卡一区二区三区| 精品视频在线免费| 免费一级片91| 自拍av一区二区三区| 欧美精品v日韩精品v韩国精品v| 国产精品一区二区三区乱码 | 综合久久综合久久| 欧美一级艳片视频免费观看| 97精品电影院| 高清日韩电视剧大全免费| 黄色精品一二区| 波多野结衣91| 久久不见久久见免费视频7 | 一道本成人在线| 99综合电影在线视频| 99免费精品在线观看| 色狠狠色噜噜噜综合网| 99久久久国产精品| 99国产精品视频免费观看| 丰满亚洲少妇av| 99国产精品久久久久久久久久久| 97久久超碰国产精品电影| 91亚洲精品久久久蜜桃网站| 97久久精品人人做人人爽 | 国产精品国产三级国产有无不卡 | 午夜欧美一区二区三区在线播放| 亚洲激情成人在线| 亚洲va国产天堂va久久en| 亚洲第一激情av| 国产又黄又大久久| 粉嫩aⅴ一区二区三区四区| 色天天综合色天天久久| 欧美老女人在线| 久久久国产午夜精品| 伊人婷婷欧美激情| 激情小说欧美图片| 99国产欧美另类久久久精品| 91超碰这里只有精品国产| 精品国偷自产国产一区| 亚洲色图一区二区三区| 日韩高清不卡一区二区三区| 成人av网址在线| 欧美一区二区在线不卡| 亚洲视频一区二区在线观看| 久久国产精品72免费观看| voyeur盗摄精品| 欧美成人伊人久久综合网| 中文字幕欧美一区| 韩国欧美一区二区| 国产精品每日更新在线播放网址| 日韩精品免费专区| 色美美综合视频| 中文字幕不卡一区| 国产综合久久久久久鬼色| 欧美三级蜜桃2在线观看| 中文字幕在线观看不卡视频| 国产精品1区二区.| 欧美大黄免费观看| 午夜一区二区三区视频| 色视频一区二区| 亚洲免费观看高清完整版在线观看熊| 国产经典欧美精品| 精品少妇一区二区| 精品一区二区三区在线播放视频| 在线观看视频一区二区欧美日韩| 亚洲图片欧美激情| 91亚洲精华国产精华精华液| 亚洲婷婷综合久久一本伊一区| 成人动漫精品一区二区| 国产精品白丝在线| 久久伊人中文字幕| 不卡一区二区在线| 自拍偷拍国产亚洲| 欧洲在线/亚洲| 日韩国产欧美在线视频| 精品国产sm最大网站免费看| 国产美女久久久久| 亚洲欧洲韩国日本视频| 日本乱人伦一区| 水蜜桃久久夜色精品一区的特点| 日韩午夜中文字幕| 成人午夜又粗又硬又大| 亚洲在线免费播放| 91精品国产色综合久久不卡电影| 久久aⅴ国产欧美74aaa| 国产精品女同一区二区三区| 欧美色综合久久| 国产精品一区二区三区网站| 亚洲综合区在线| 日韩精品中文字幕在线一区| 成人国产精品免费| 男女性色大片免费观看一区二区 | 久久久久久久久久久99999| 91看片淫黄大片一级在线观看| 日本人妖一区二区| 亚洲人成精品久久久久久| 欧美成人精精品一区二区频| 91豆麻精品91久久久久久| 极品少妇一区二区三区精品视频 | 韩国三级在线一区| 亚洲国产sm捆绑调教视频| 欧美激情综合五月色丁香小说| 欧美电影影音先锋| 99精品桃花视频在线观看| 久草在线在线精品观看| 亚洲午夜久久久久久久久电影院| 久久久久久久久久久久电影 | 国产精品国产精品国产专区不蜜 | 在线观看免费一区| 成人国产免费视频| 成人午夜电影久久影院| 玖玖九九国产精品| 日本午夜精品一区二区三区电影| 亚洲国产美女搞黄色| 亚洲毛片av在线| 亚洲一区二区三区在线播放 | 中文字幕中文在线不卡住| 久久久精品影视| 2019国产精品| 国产欧美日韩卡一| 欧美激情在线观看视频免费| 欧美激情综合五月色丁香小说| 国产亚洲精品福利| 国产精品久久毛片av大全日韩| 中文在线一区二区| 亚洲欧美色综合| 亚洲电影在线播放| 性做久久久久久免费观看| 天天综合网天天综合色| 日本不卡1234视频| 国产一区二区三区日韩| 日韩欧美亚洲一区二区| 久久伊人中文字幕| 中文字幕中文字幕一区二区 | 日韩美女视频在线| 欧美国产激情二区三区| 亚洲午夜久久久久久久久久久| 男女男精品视频| 97精品国产露脸对白| 欧美人牲a欧美精品| 亚洲第一激情av| 国内精品第一页| 色综合天天综合网天天看片| 7777精品久久久大香线蕉| 久久久亚洲国产美女国产盗摄| 一区二区在线观看免费| 久久国产人妖系列| 欧美色综合影院| 国产精品超碰97尤物18| 国内精品国产三级国产a久久| 在线视频观看一区| 精品国产乱码久久久久久老虎 | 国产在线视频精品一区| 欧美三级电影一区| 国产精品成人午夜| 国产在线观看免费一区| 91精品国产综合久久精品麻豆| 亚洲婷婷在线视频| av亚洲精华国产精华精华| 亚洲精品在线观看网站| 午夜精品免费在线观看| 欧美性色黄大片| 亚洲女同一区二区| 成人av网址在线| 国产欧美一区二区三区沐欲| 麻豆国产精品官网| 日韩小视频在线观看专区| 亚洲大片在线观看| 欧美日韩免费一区二区三区| 亚洲综合色区另类av| 91蜜桃视频在线| 成人欧美一区二区三区1314| 国产不卡在线一区| 国产精品拍天天在线| 丁香婷婷综合激情五月色| 国产精品少妇自拍| caoporm超碰国产精品| 亚洲视频图片小说| 欧美色图一区二区三区| 日本不卡视频一二三区| 精品成人一区二区| 成人国产精品免费| 亚洲在线中文字幕| 欧美一卡二卡在线| 国产伦精一区二区三区| 亚洲欧美日韩中文字幕一区二区三区| 色妹子一区二区| 久久成人久久爱| 亚洲日韩欧美一区二区在线| 精品污污网站免费看| 另类小说综合欧美亚洲| 国产精品久久久久影院色老大 | 91精品国产欧美一区二区成人| 狠狠色狠狠色综合系列| 亚洲视频一区二区在线观看| 日韩欧美在线网站| av亚洲精华国产精华| 久久99精品久久久| 一区二区中文字幕在线| 日韩视频免费观看高清完整版在线观看 |