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

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

?? lance.c

?? LINUX1.0源代碼,代碼條理清晰
?? C
?? 第 1 頁 / 共 2 頁
字號:
/* lance.c: An AMD LANCE ethernet driver for linux. */
/*
    Written 1993 by Donald Becker.

    Copyright 1993 United States Government as represented by the
    Director, National Security Agency.  This software may be used and
    distributed according to the terms of the GNU Public License,
    incorporated herein by reference.

    This driver is for the Allied Telesis AT1500 and HP J2405A, and should work
    with most other LANCE-based bus-master (NE2100 clone) ethercards.

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

static char *version = "lance.c:v0.14g 12/21/93 becker@super.org\n";

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

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

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

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

struct device *init_etherdev(struct device *dev, int sizeof_private,
			     unsigned long *mem_startp);

#ifdef LANCE_DEBUG
int lance_debug = LANCE_DEBUG;
#else
int lance_debug = 1;
#endif

#ifndef LANCE_DMA
#define LANCE_DMA	5
#endif

/*
  		Theory of Operation

I. Board Compatibility

This device driver is designed for the AMD 79C960, the "PCnet-ISA
single-chip ethernet controller for ISA".  This chip is used in a wide
variety of boards from vendors such as Allied Telesis, HP, Kingston,
and Boca.  This driver is also intended to work with older AMD 7990
designs, such as the NE1500 and NE2100.  For convenience, I use the name
LANCE to refer to either AMD chip.

II. Board-specific settings

The driver is designed to work the boards that use the faster
bus-master mode, rather than in shared memory mode.  (Only older designs
have on-board buffer memory needed to support the slower shared memory mode.)

Most boards have jumpered settings for the I/O base, IRQ line, and DMA channel.
This driver probes the likely base addresses, {0x300, 0x320, 0x340, 0x360}.
After the board is found it generates an DMA-timeout interrupt and uses
autoIRQ to find the IRQ line.  The DMA channel defaults to LANCE_DMA, or it
can be set with the low bits of the otherwise-unused dev->mem_start value.

The HP-J2405A board is an exception: with this board it's easy to read the
EEPROM-set values for the base, IRQ, and DMA.  Of course you must already
_know_ the base address, but that entry is for changing the EEPROM.

III. Driver operation

IIIa. Ring buffers
The LANCE uses ring buffers of Tx and Rx descriptors.  Each entry describes
the base and length of the data buffer, along with status bits.  The length
of these buffers is set by LANCE_LOG_{RX,TX}_BUFFERS, which is log_2() of
the buffer length (rather than being directly the buffer length) for
implementation ease.  The current values are 2 (Tx) and 4 (Rx), which leads to
ring sizes of 4 (Tx) and 16 (Rx).  Increasing the number of ring entries
needlessly uses extra space and reduces the chance that an upper layer will
be able to reorder queued Tx packets based on priority.  Decreasing the number
of entries makes it more difficult to achieve back-to-back packet transmission
and increases the chance that Rx ring will overflow.  (Consider the worst case
of receiving back-to-back minimum-sized packets.)

The LANCE has the capability to "chain" both Rx and Tx buffers, but this driver
statically allocates full-sized (slightly oversized -- PKT_BUF_SZ) buffers to
avoid the administrative overhead. For the Rx side this avoids dynamically
allocating full-sized buffers "just in case", at the expense of a
memory-to-memory data copy for each packet received.  For most systems this
is an good tradeoff: the Rx buffer will always be in low memory, the copy
is inexpensive, and it primes the cache for later packet processing.  For Tx
the buffers are only used when needed as low-memory bounce buffers.

IIIB. 16M memory limitations.
For the ISA bus master mode all structures used directly by the LANCE,
the initialization block, Rx and Tx rings, and data buffers, must be
accessable from the ISA bus, i.e. in the lower 16M of real memory.
This is a problem for current Linux kernels on >16M machines. The network
devices are initialized after memory initialization, and the kernel doles out
memory from the top of memory downward.  The current solution is to have a
special network initialization routine that's called before memory
initialization; this will eventually be generalized for all network devices.
As mentioned before, low-memory "bounce-buffers" are used when needed.

IIIC. Synchronization
The driver runs as two independent, single-threaded flows of control.  One
is the send-packet routine, which enforces single-threaded use by the
dev->tbusy flag.  The other thread is the interrupt handler, which is single
threaded by the hardware and other software.

The send packet thread has partial control over the Tx ring and 'dev->tbusy'
flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
queue slot is empty, it clears the tbusy flag when finished otherwise it sets
the 'lp->tx_full' flag.

The interrupt handler has exclusive control over the Rx ring and records stats
from the Tx ring.  (The Tx-done interrupt can't be selectively turned off, so
we can't avoid the interrupt overhead by having the Tx routine reap the Tx
stats.)  After reaping the stats, it marks the queue entry as empty by setting
the 'base' to zero.  Iff the 'lp->tx_full' flag is set, it clears both the
tx_full and tbusy flags.

*/

/* Set the number of Tx and Rx buffers, using Log_2(# buffers).
   Reasonable default values are 4 Tx buffers, and 16 Rx buffers.
   That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4). */
#ifndef LANCE_LOG_TX_BUFFERS
#define LANCE_LOG_TX_BUFFERS 4
#define LANCE_LOG_RX_BUFFERS 4
#endif

#define TX_RING_SIZE		(1 << (LANCE_LOG_TX_BUFFERS))
#define TX_RING_MOD_MASK	(TX_RING_SIZE - 1)
#define TX_RING_LEN_BITS	((LANCE_LOG_TX_BUFFERS) << 29)

#define RX_RING_SIZE		(1 << (LANCE_LOG_RX_BUFFERS))
#define RX_RING_MOD_MASK	(RX_RING_SIZE - 1)
#define RX_RING_LEN_BITS	((LANCE_LOG_RX_BUFFERS) << 29)

#define PKT_BUF_SZ	1544

/* Offsets from base I/O address. */
#define LANCE_DATA 0x10
#define LANCE_ADDR 0x12
#define LANCE_RESET 0x14
#define LANCE_BUS_IF 0x16
#define LANCE_TOTAL_SIZE 0x18

/* The LANCE Rx and Tx ring descriptors. */
struct lance_rx_head {
    int	base;
    short buf_length;		/* This length is 2's complement (negative)! */
    short msg_length;		/* This length is "normal". */
};

struct lance_tx_head {
    int	  base;
    short length;		/* Length is 2's complement (negative)! */
    short misc;
};

/* The LANCE initialization block, described in databook. */
struct lance_init_block {
    unsigned short mode;	/* Pre-set mode (reg. 15) */
    unsigned char phys_addr[6];	/* Physical ethernet address */
    unsigned filter[2];		/* Multicast filter (unused). */
    /* Receive and transmit ring base, along with extra bits. */
    unsigned rx_ring;		/* Tx and Rx ring base pointers */
    unsigned tx_ring;
};

struct lance_private {
    char devname[8];
    /* These must aligned on 8-byte boundaries. */
    struct lance_rx_head rx_ring[RX_RING_SIZE];
    struct lance_tx_head tx_ring[TX_RING_SIZE];
    struct lance_init_block	init_block;
    long rx_buffs;		/* Address of Rx and Tx buffers. */
    /* Tx low-memory "bounce buffer" address. */
    char (*tx_bounce_buffs)[PKT_BUF_SZ];
    int	cur_rx, cur_tx;		/* The next free ring entry */
    int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
    int dma;
    struct enet_statistics stats;
    char old_lance;
    int pad0, pad1;		/* Used for alignment */
};

unsigned long lance_probe1(short ioaddr, unsigned long mem_start);
static int lance_open(struct device *dev);
static void lance_init_ring(struct device *dev);
static int lance_start_xmit(struct sk_buff *skb, struct device *dev);
static int lance_rx(struct device *dev);
static void lance_interrupt(int reg_ptr);
static int lance_close(struct device *dev);
static struct enet_statistics *lance_get_stats(struct device *dev);
#ifdef HAVE_MULTICAST
static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
#endif



unsigned long lance_init(unsigned long mem_start, unsigned long mem_end)
{
    int *port, ports[] = {0x300, 0x320, 0x340, 0x360, 0};

    for (port = &ports[0]; *port; port++) {
	int ioaddr = *port;

	if (   check_region(ioaddr, LANCE_TOTAL_SIZE) == 0
	    && inb(ioaddr + 14) == 0x57
	    && inb(ioaddr + 15) == 0x57) {
	    mem_start = lance_probe1(ioaddr, mem_start);
	}
    }

    return mem_start;
}

unsigned long lance_probe1(short ioaddr, unsigned long mem_start)
{
    struct device *dev;
    struct lance_private *lp;
    int hpJ2405A = 0;
    int i, reset_val;

    hpJ2405A = (inb(ioaddr) == 0x08 && inb(ioaddr+1) == 0x00
		&& inb(ioaddr+2) == 0x09);

    /* Reset the LANCE.  */
    reset_val = inw(ioaddr+LANCE_RESET); /* Reset the LANCE */

    /* The Un-Reset needed is only needed for the real NE2100, and will
       confuse the HP board. */
    if (!hpJ2405A)
	outw(reset_val, ioaddr+LANCE_RESET);

    outw(0x0000, ioaddr+LANCE_ADDR); /* Switch to window 0 */
    if (inw(ioaddr+LANCE_DATA) != 0x0004)
	return mem_start;

    dev = init_etherdev(0, sizeof(struct lance_private)
			+ PKT_BUF_SZ*(RX_RING_SIZE + TX_RING_SIZE),
			&mem_start);

    printk("%s: LANCE at %#3x,", dev->name, ioaddr);

    /* There is a 16 byte station address PROM at the base address.
       The first six bytes are the station address. */
    for (i = 0; i < 6; i++)
	printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));

    dev->base_addr = ioaddr;
    snarf_region(ioaddr, LANCE_TOTAL_SIZE);

    /* Make certain the data structures used by the LANCE are aligned. */
    dev->priv = (void *)(((int)dev->priv + 7) & ~7);
    lp = (struct lance_private *)dev->priv;
    lp->rx_buffs = (long)dev->priv + sizeof(struct lance_private);
    lp->tx_bounce_buffs = (char (*)[PKT_BUF_SZ])
			   (lp->rx_buffs + PKT_BUF_SZ*RX_RING_SIZE);

#ifndef final_version
    /* This should never happen. */
    if ((int)(lp->rx_ring) & 0x07) {
	printk(" **ERROR** LANCE Rx and Tx rings not on even boundary.\n");
	return mem_start;
    }
#endif

    outw(88, ioaddr+LANCE_ADDR);
    lp->old_lance = (inw(ioaddr+LANCE_DATA) != 0x3003);

#if defined(notdef)
    printk(lp->old_lance ? " original LANCE (%04x)" : " PCnet-ISA LANCE (%04x)",
	   inw(ioaddr+LANCE_DATA));
#endif

    lp->init_block.mode = 0x0003;	/* Disable Rx and Tx. */
    for (i = 0; i < 6; i++)
	lp->init_block.phys_addr[i] = dev->dev_addr[i];
    lp->init_block.filter[0] = 0x00000000;
    lp->init_block.filter[1] = 0x00000000;
    lp->init_block.rx_ring = (int)lp->rx_ring | RX_RING_LEN_BITS;
    lp->init_block.tx_ring = (int)lp->tx_ring | TX_RING_LEN_BITS;

    outw(0x0001, ioaddr+LANCE_ADDR);
    outw((short) (int) &lp->init_block, ioaddr+LANCE_DATA);
    outw(0x0002, ioaddr+LANCE_ADDR);
    outw(((int)&lp->init_block) >> 16, ioaddr+LANCE_DATA);
    outw(0x0000, ioaddr+LANCE_ADDR);

    if (hpJ2405A) {
	char dma_tbl[4] = {3, 5, 6, 7};
	char irq_tbl[8] = {3, 4, 5, 9, 10, 11, 12, 15};
	short reset_val = inw(ioaddr+LANCE_RESET);
	dev->dma = dma_tbl[(reset_val >> 2) & 3];
	dev->irq = irq_tbl[(reset_val >> 4) & 7];
	printk(" HP J2405A IRQ %d DMA %d.\n", dev->irq, dev->dma);
    } else {
	/* The DMA channel may be passed in on this parameter. */
	if (dev->mem_start & 0x07)
	    dev->dma = dev->mem_start & 0x07;
	else if (dev->dma == 0)
	    dev->dma = LANCE_DMA;

	/* To auto-IRQ we enable the initialization-done and DMA err,
	   interrupts. For now we will always get a DMA error. */
	if (dev->irq < 2) {

	    autoirq_setup(0);

	    /* Trigger an initialization just for the interrupt. */
	    outw(0x0041, ioaddr+LANCE_DATA);

	    dev->irq = autoirq_report(1);
	    if (dev->irq)
		printk(", probed IRQ %d, fixed at DMA %d.\n",
		       dev->irq, dev->dma);
	    else {
		printk(", failed to detect IRQ line.\n");
		return mem_start;
	    }
	} else
	    printk(" assigned IRQ %d DMA %d.\n", dev->irq, dev->dma);
    }

    if (! lp->old_lance) {
	/* Turn on auto-select of media (10baseT or BNC) so that the user
	   can watch the LEDs even if the board isn't opened. */
	outw(0x0002, ioaddr+LANCE_ADDR);
	outw(0x0002, ioaddr+LANCE_BUS_IF);
    }

    if (lance_debug > 0)
	printk(version);

    /* The LANCE-specific entries in the device structure. */
    dev->open = &lance_open;
    dev->hard_start_xmit = &lance_start_xmit;
    dev->stop = &lance_close;
    dev->get_stats = &lance_get_stats;
#ifdef HAVE_MULTICAST
    dev->set_multicast_list = &set_multicast_list;
#endif

    return mem_start;
}


static int
lance_open(struct device *dev)
{
    struct lance_private *lp = (struct lance_private *)dev->priv;
    int ioaddr = dev->base_addr;
    int i;

    if (request_irq(dev->irq, &lance_interrupt)) {
	return -EAGAIN;
    }

    if (request_dma(dev->dma)) {
	free_irq(dev->irq);
	return -EAGAIN;
    }
    irq2dev_map[dev->irq] = dev;

    /* Reset the LANCE */
    inw(ioaddr+LANCE_RESET);

    /* The DMA controller is used as a no-operation slave, "cascade mode". */
    enable_dma(dev->dma);
    set_dma_mode(dev->dma, DMA_MODE_CASCADE);

    /* Un-Reset the LANCE, needed only for the NE2100. */
    if (lp->old_lance)
	outw(0, ioaddr+LANCE_RESET);

    if (! lp->old_lance) {
	/* This is 79C960-specific: Turn on auto-select of media (AUI, BNC). */
	outw(0x0002, ioaddr+LANCE_ADDR);
	outw(0x0002, ioaddr+LANCE_BUS_IF);
    }

    if (lance_debug > 1)
	printk("%s: lance_open() irq %d dma %d tx/rx rings %#x/%#x init %#x.\n",
	       dev->name, dev->irq, dev->dma, (int) lp->tx_ring, (int) lp->rx_ring,
	       (int) &lp->init_block);

    lance_init_ring(dev);
    /* Re-initialize the LANCE, and start it when done. */
    outw(0x0001, ioaddr+LANCE_ADDR);
    outw((short) (int) &lp->init_block, ioaddr+LANCE_DATA);
    outw(0x0002, ioaddr+LANCE_ADDR);
    outw(((int)&lp->init_block) >> 16, ioaddr+LANCE_DATA);

    outw(0x0004, ioaddr+LANCE_ADDR);
    outw(0x0d15, ioaddr+LANCE_DATA);

    outw(0x0000, ioaddr+LANCE_ADDR);
    outw(0x0001, ioaddr+LANCE_DATA);

    dev->tbusy = 0;
    dev->interrupt = 0;
    dev->start = 1;
    i = 0;
    while (i++ < 100)
	if (inw(ioaddr+LANCE_DATA) & 0x0100)
	    break;
    outw(0x0142, ioaddr+LANCE_DATA);

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
国产伦理精品不卡| 亚洲一区二区三区三| 国产一区二区三区四区在线观看 | 99国内精品久久| 日韩一区在线播放| 日韩免费观看2025年上映的电影| 日本亚洲欧美天堂免费| 精品国产污污免费网站入口 | 2024国产精品| 国产成人亚洲精品青草天美| 国产精品理论在线观看| 日本黄色一区二区| 蜜臀久久久99精品久久久久久| 精品人在线二区三区| 国产成人综合在线播放| 国产精品久久网站| 欧美视频一区二区三区| 国产资源在线一区| 亚洲毛片av在线| 日韩精品中午字幕| 99久久777色| 男女男精品网站| 国产精品毛片大码女人| 在线一区二区观看| 精品制服美女丁香| 亚洲精品你懂的| 欧美大片日本大片免费观看| 国产xxx精品视频大全| 亚洲国产欧美日韩另类综合 | 日韩毛片在线免费观看| 欧美日韩国产精品成人| 成人小视频免费观看| 亚洲成人中文在线| 久久欧美一区二区| 欧美日韩国产综合草草| 国产aⅴ精品一区二区三区色成熟| 一个色在线综合| 久久青草国产手机看片福利盒子| 在线免费视频一区二区| 精品一区二区三区欧美| 亚洲综合色自拍一区| 国产精品无码永久免费888| 欧美日韩国产成人在线91| bt欧美亚洲午夜电影天堂| 蜜桃精品在线观看| 亚洲一区免费视频| 国产精品久久久久久久久晋中 | 日韩欧美二区三区| 91久久久免费一区二区| 成人一区二区三区| 九一九一国产精品| 全国精品久久少妇| 亚洲第一成年网| 亚洲男人的天堂av| 国产精品乱子久久久久| 久久久久久久久久电影| 欧美一级二级三级蜜桃| 欧美人狂配大交3d怪物一区| 91在线你懂得| 欧美男生操女生| 日本韩国一区二区三区视频| 成人黄色在线看| 国产美女视频一区| 国产呦萝稀缺另类资源| 久久国产麻豆精品| 麻豆国产精品一区二区三区 | 国产一区二区三区视频在线播放| 天天影视涩香欲综合网 | 亚洲欧美中日韩| 国产女人18毛片水真多成人如厕| 欧美哺乳videos| 日韩午夜激情视频| 91精品国产高清一区二区三区 | 色综合久久88色综合天天免费| 粉嫩av亚洲一区二区图片| 国产黄色精品网站| 国产精品自在在线| 国产成人精品亚洲日本在线桃色| 狠狠v欧美v日韩v亚洲ⅴ| 久久国产乱子精品免费女| 国产一区二区三区久久久| 精品一区二区三区久久| 国产盗摄一区二区三区| 成人久久视频在线观看| 91在线无精精品入口| 91高清在线观看| 欧美精品v日韩精品v韩国精品v| 欧美日韩精品二区第二页| 欧美一区二区三区思思人| 日韩视频永久免费| 国产亚洲欧美激情| 亚洲欧洲一区二区三区| 一区二区三区欧美| 日本三级韩国三级欧美三级| 久久成人综合网| 粉嫩在线一区二区三区视频| 9i在线看片成人免费| 色94色欧美sute亚洲线路一ni| 欧美午夜精品一区二区三区| 911精品产国品一二三产区| 亚洲精品一区二区三区影院 | 欧美性受xxxx黑人xyx性爽| 欧美放荡的少妇| 国产片一区二区三区| 亚洲视频网在线直播| 奇米一区二区三区| 成人av资源站| 欧美日韩成人激情| 亚洲一区二区av在线| 麻豆免费精品视频| 99re热视频精品| 欧美一级二级三级蜜桃| 欧美国产日本韩| 天天av天天翘天天综合网色鬼国产 | 日本一区二区三区久久久久久久久不| 国产精品理伦片| 免费观看一级欧美片| 成人小视频免费观看| 精品视频免费看| 欧美激情中文字幕| 五月婷婷色综合| 99精品桃花视频在线观看| 7777精品伊人久久久大香线蕉| 欧美国产精品久久| 日韩精品三区四区| 99久久国产综合色|国产精品| 欧美xxx久久| 午夜精品久久久久影视| 国产99精品国产| 日韩欧美在线一区二区三区| 亚洲人成在线观看一区二区| 精品在线观看视频| 宅男在线国产精品| 亚洲欧美视频一区| 国产精品一区二区果冻传媒| 欧美日韩久久一区| 亚洲激情第一区| 成人一级视频在线观看| 精品国产一区二区三区久久久蜜月 | 亚洲视频免费在线观看| 国产美女视频91| 日韩精品一区二区三区三区免费| 亚洲欧美日韩综合aⅴ视频| 国产成人综合亚洲网站| 日韩天堂在线观看| 视频一区中文字幕国产| 色婷婷亚洲综合| 一区视频在线播放| 成人av资源下载| 亚洲国产成人私人影院tom| 韩国成人在线视频| 日韩精品一区二区三区四区视频 | 国产激情一区二区三区桃花岛亚洲| 欧美日韩亚州综合| 亚洲视频每日更新| 99久久精品久久久久久清纯| 国产精品日产欧美久久久久| 国产黄人亚洲片| 欧美激情综合五月色丁香小说| 黄页视频在线91| 精品国产91洋老外米糕| 久久福利资源站| 久久午夜国产精品| 国产一区二区日韩精品| 精品福利一区二区三区| 蜜桃视频一区二区三区| 欧美mv日韩mv亚洲| 国产原创一区二区| 亚洲婷婷在线视频| 一本久久a久久精品亚洲| 一区二区三区国产精华| 色中色一区二区| 亚洲一二三四区| 91精品欧美综合在线观看最新| 午夜精品久久久久久久久久久 | 欧美电影一区二区| 琪琪久久久久日韩精品| 精品久久久影院| 国产电影精品久久禁18| 国产精品日韩成人| 欧美专区日韩专区| 免费一级片91| 久久久综合精品| zzijzzij亚洲日本少妇熟睡| 中文字幕在线一区免费| 91成人看片片| 全国精品久久少妇| 久久免费视频一区| 色综合中文字幕| 亚洲成av人在线观看| 91精品国产综合久久久久久漫画 | 一色桃子久久精品亚洲| 欧美性欧美巨大黑白大战| 七七婷婷婷婷精品国产| 国产三级三级三级精品8ⅰ区| 99re亚洲国产精品| 日本不卡视频一二三区| 欧美经典一区二区| 欧美丝袜丝nylons| 精品一区二区免费视频|