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

📄 pcnet32.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 2 页
字号:
#define EB52#ifdef EB50#define __unused __attribute__((unused))#endif/****************************************************************************    pcnet32.c -- Etherboot device driver for the AMD PCnet32*    Written 2003-2003 by Timothy Legge <tlegge@rogers.com>**    This program is free software; you can redistribute it and/or modify*    it under the terms of the GNU General Public License as published by*    the Free Software Foundation; either version 2 of the License, or*    (at your option) any later version.**    This program is distributed in the hope that it will be useful,*    but WITHOUT ANY WARRANTY; without even the implied warranty of*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the*    GNU General Public License for more details.**    You should have received a copy of the GNU General Public License*    along with this program; if not, write to the Free Software*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.**    Portions of this code based on:*		pcnet32.c: An AMD PCnet32 ethernet driver for linux:**	(C) 1996-1999 Thomas Bogendoerfer*		See Linux Driver for full information*	*	The transmit and poll functions were written with reference to:*	lance.c - LANCE NIC driver for Etherboot written by Ken Yap *	*	Linux Driver Version 1.27a, 10.02.2002* * *    REVISION HISTORY:*    ================*    v1.0	08-06-2003	timlegge	Initial port of Linux driver*    v1.1	08-23-2003	timlegge	Add multicast support*    v1.2	01-17-2004	timlegge	Initial driver output cleanup*    *    Indent Options: indent -kr -i8***************************************************************************//* to get some global routines like printf */#include "etherboot.h"/* to get the interface to the body of the program */#include "nic.h"/* to get the PCI support functions, if this is a PCI NIC */#include "pci.h"/* Include the time functions */#include "timer.h"/* void hex_dump(const char *data, const unsigned int len); *//* Etherboot Specific definations */#define drv_version "v1.2"#define drv_date "01-17-2004"typedef unsigned char u8;typedef signed char s8;typedef unsigned short u16;typedef signed short s16;typedef unsigned int u32;typedef signed int s32;static u32 ioaddr;		/* Globally used for the card's io address */#ifdef EB50#define cpu_to_le32(val) (val)#define le16_to_cpu(val) (val)#define le32_to_cpu(val) (val)#define virt_to_bus(x) ((unsigned long)x)#define bus_to_virt(x) ((unsigned long) x)#endif/* Condensed operations for readability. */#define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))#define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))/* End Etherboot Specific */int cards_found /* __initdata */ ;#ifdef REMOVE/* FIXME: Remove these they are probably pointless *//*  * VLB I/O addresses  */static unsigned int pcnet32_portlist[] /*__initdata */  ={ 0x300, 0x320, 0x340, 0x360, 0 };static int pcnet32_debug = 1;static int tx_start = 1;	/* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */static int pcnet32vlb;		/* check for VLB cards ? */static struct net_device *pcnet32_dev;static int max_interrupt_work = 80;static int rx_copybreak = 200;#endif#define PCNET32_PORT_AUI      0x00#define PCNET32_PORT_10BT     0x01#define PCNET32_PORT_GPSI     0x02#define PCNET32_PORT_MII      0x03#define PCNET32_PORT_PORTSEL  0x03#define PCNET32_PORT_ASEL     0x04#define PCNET32_PORT_100      0x40#define PCNET32_PORT_FD	      0x80#define PCNET32_DMA_MASK 0xffffffff/* * table to translate option values from tulip * to internal options */static unsigned char options_mapping[] = {	PCNET32_PORT_ASEL,	/*  0 Auto-select      */	PCNET32_PORT_AUI,	/*  1 BNC/AUI          */	PCNET32_PORT_AUI,	/*  2 AUI/BNC          */	PCNET32_PORT_ASEL,	/*  3 not supported    */	PCNET32_PORT_10BT | PCNET32_PORT_FD,	/*  4 10baseT-FD       */	PCNET32_PORT_ASEL,	/*  5 not supported    */	PCNET32_PORT_ASEL,	/*  6 not supported    */	PCNET32_PORT_ASEL,	/*  7 not supported    */	PCNET32_PORT_ASEL,	/*  8 not supported    */	PCNET32_PORT_MII,	/*  9 MII 10baseT      */	PCNET32_PORT_MII | PCNET32_PORT_FD,	/* 10 MII 10baseT-FD   */	PCNET32_PORT_MII,	/* 11 MII (autosel)    */	PCNET32_PORT_10BT,	/* 12 10BaseT          */	PCNET32_PORT_MII | PCNET32_PORT_100,	/* 13 MII 100BaseTx    */	PCNET32_PORT_MII | PCNET32_PORT_100 | PCNET32_PORT_FD,	/* 14 MII 100BaseTx-FD */	PCNET32_PORT_ASEL	/* 15 not supported    */};#define MAX_UNITS 8		/* More are supported, limit only on options */static int options[MAX_UNITS];static int full_duplex[MAX_UNITS];/* *				Theory of Operation *  * This driver uses the same software structure as the normal lance * driver. So look for a verbose description in lance.c. The differences * to the normal lance driver is the use of the 32bit mode of PCnet32 * and PCnetPCI chips. Because these chips are 32bit chips, there is no * 16MB limitation and we don't need bounce buffers. *//* * 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 PCNET32_LOG_TX_BUFFERS#define PCNET32_LOG_TX_BUFFERS 1#define PCNET32_LOG_RX_BUFFERS 2#endif#define TX_RING_SIZE		(1 << (PCNET32_LOG_TX_BUFFERS))#define TX_RING_MOD_MASK	(TX_RING_SIZE - 1)/* FIXME: Fix this to allow multiple tx_ring descriptors */#define TX_RING_LEN_BITS	0x0000	/*PCNET32_LOG_TX_BUFFERS) << 12) */#define RX_RING_SIZE		(1 << (PCNET32_LOG_RX_BUFFERS))#define RX_RING_MOD_MASK	(RX_RING_SIZE - 1)#define RX_RING_LEN_BITS	((PCNET32_LOG_RX_BUFFERS) << 4)#define PKT_BUF_SZ		1544/* Offsets from base I/O address. */#define PCNET32_WIO_RDP		0x10#define PCNET32_WIO_RAP		0x12#define PCNET32_WIO_RESET	0x14#define PCNET32_WIO_BDP		0x16#define PCNET32_DWIO_RDP	0x10#define PCNET32_DWIO_RAP	0x14#define PCNET32_DWIO_RESET	0x18#define PCNET32_DWIO_BDP	0x1C#define PCNET32_TOTAL_SIZE	0x20/* Buffers for the tx and Rx *//* Create a static buffer of size PKT_BUF_SZ for eachTX Descriptor.  All descriptors point to apart of this buffer */static unsigned char txb[PKT_BUF_SZ * TX_RING_SIZE]    __attribute__ ((aligned(16)));/* Create a static buffer of size PKT_BUF_SZ for eachRX Descriptor   All descriptors point to apart of this buffer */static unsigned char rxb[RX_RING_SIZE * PKT_BUF_SZ]    __attribute__ ((aligned(16)));/* The PCNET32 Rx and Tx ring descriptors. */struct pcnet32_rx_head {	u32 base;	s16 buf_length;	s16 status;	u32 msg_length;	u32 reserved;};struct pcnet32_tx_head {	u32 base;	s16 length;	s16 status;	u32 misc;	u32 reserved;};/* The PCNET32 32-Bit initialization block, described in databook. */struct pcnet32_init_block {	u16 mode;	u16 tlen_rlen;	u8 phys_addr[6];	u16 reserved;	u32 filter[2];	/* Receive and transmit ring base, along with extra bits. */	u32 rx_ring;	u32 tx_ring;};/* PCnet32 access functions */struct pcnet32_access {	u16(*read_csr) (unsigned long, int);	void (*write_csr) (unsigned long, int, u16);	 u16(*read_bcr) (unsigned long, int);	void (*write_bcr) (unsigned long, int, u16);	 u16(*read_rap) (unsigned long);	void (*write_rap) (unsigned long, u16);	void (*reset) (unsigned long);};/* Define the TX Descriptor */static struct pcnet32_tx_head tx_ring[TX_RING_SIZE]    __attribute__ ((aligned(16)));/* Define the RX Descriptor */static struct pcnet32_rx_head rx_ring[RX_RING_SIZE]    __attribute__ ((aligned(16)));/* * The first three fields of pcnet32_private are read by the ethernet device  * so we allocate the structure should be allocated by pci_alloc_consistent(). */struct pcnet32_private {	struct pcnet32_init_block init_block;	struct pci_dev *pci_dev;	/* Pointer to the associated pci device structure */	const char *name;	/* The saved address of a sent-in-place packet/buffer, for skfree(). */	struct sk_buff *tx_skbuff[TX_RING_SIZE];	struct sk_buff *rx_skbuff[RX_RING_SIZE];	struct pcnet32_access a;	unsigned int cur_rx, cur_tx;	/* The next free ring entry */	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */	char tx_full;	int options;	int shared_irq:1,	/* shared irq possible */	 ltint:1,		/* enable TxDone-intr inhibitor */	 dxsuflo:1,		/* disable transmit stop on uflo */	 mii:1;			/* mii port available */	struct net_device *next;	int full_duplex:1;} lpx;static struct pcnet32_private *lp;enum pci_flags_bit {	PCI_USES_IO = 1, PCI_USES_MEM = 2, PCI_USES_MASTER = 4,	PCI_ADDR0 = 0x10 << 0, PCI_ADDR1 = 0x10 << 1, PCI_ADDR2 =	    0x10 << 2, PCI_ADDR3 = 0x10 << 3,};static u16 pcnet32_wio_read_csr(unsigned long addr, int index){	outw(index, addr + PCNET32_WIO_RAP);	return inw(addr + PCNET32_WIO_RDP);}static void pcnet32_wio_write_csr(unsigned long addr, int index, u16 val){	outw(index, addr + PCNET32_WIO_RAP);	outw(val, addr + PCNET32_WIO_RDP);}static u16 pcnet32_wio_read_bcr(unsigned long addr, int index){	outw(index, addr + PCNET32_WIO_RAP);	return inw(addr + PCNET32_WIO_BDP);}static void pcnet32_wio_write_bcr(unsigned long addr, int index, u16 val){	outw(index, addr + PCNET32_WIO_RAP);	outw(val, addr + PCNET32_WIO_BDP);}static u16 pcnet32_wio_read_rap(unsigned long addr){	return inw(addr + PCNET32_WIO_RAP);}static void pcnet32_wio_write_rap(unsigned long addr, u16 val){	outw(val, addr + PCNET32_WIO_RAP);}static void pcnet32_wio_reset(unsigned long addr){	inw(addr + PCNET32_WIO_RESET);}static int pcnet32_wio_check(unsigned long addr){	outw(88, addr + PCNET32_WIO_RAP);	return (inw(addr + PCNET32_WIO_RAP) == 88);}static struct pcnet32_access pcnet32_wio = {	read_csr:pcnet32_wio_read_csr,	write_csr:pcnet32_wio_write_csr,	read_bcr:pcnet32_wio_read_bcr,	write_bcr:pcnet32_wio_write_bcr,	read_rap:pcnet32_wio_read_rap,	write_rap:pcnet32_wio_write_rap,	reset:pcnet32_wio_reset};static u16 pcnet32_dwio_read_csr(unsigned long addr, int index){	outl(index, addr + PCNET32_DWIO_RAP);	return (inl(addr + PCNET32_DWIO_RDP) & 0xffff);}static void pcnet32_dwio_write_csr(unsigned long addr, int index, u16 val){	outl(index, addr + PCNET32_DWIO_RAP);	outl(val, addr + PCNET32_DWIO_RDP);}static u16 pcnet32_dwio_read_bcr(unsigned long addr, int index){	outl(index, addr + PCNET32_DWIO_RAP);	return (inl(addr + PCNET32_DWIO_BDP) & 0xffff);}static void pcnet32_dwio_write_bcr(unsigned long addr, int index, u16 val){	outl(index, addr + PCNET32_DWIO_RAP);	outl(val, addr + PCNET32_DWIO_BDP);}static u16 pcnet32_dwio_read_rap(unsigned long addr){	return (inl(addr + PCNET32_DWIO_RAP) & 0xffff);}static void pcnet32_dwio_write_rap(unsigned long addr, u16 val){	outl(val, addr + PCNET32_DWIO_RAP);}static void pcnet32_dwio_reset(unsigned long addr){	inl(addr + PCNET32_DWIO_RESET);}static int pcnet32_dwio_check(unsigned long addr){	outl(88, addr + PCNET32_DWIO_RAP);	return ((inl(addr + PCNET32_DWIO_RAP) & 0xffff) == 88);}static struct pcnet32_access pcnet32_dwio = {	read_csr:pcnet32_dwio_read_csr,	write_csr:pcnet32_dwio_write_csr,	read_bcr:pcnet32_dwio_read_bcr,	write_bcr:pcnet32_dwio_write_bcr,	read_rap:pcnet32_dwio_read_rap,	write_rap:pcnet32_dwio_write_rap,	reset:pcnet32_dwio_reset};/* Initialize the PCNET32 Rx and Tx rings. */static int pcnet32_init_ring(struct nic *nic){	int i;	lp->tx_full = 0;	lp->cur_rx = lp->cur_tx = 0;	lp->dirty_rx = lp->dirty_tx = 0;	for (i = 0; i < RX_RING_SIZE; i++) {		rx_ring[i].base = (u32) virt_to_le32desc(&rxb[i]);		rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ);		rx_ring[i].status = le16_to_cpu(0x8000);	}	/* The Tx buffer address is filled in as needed, but we do need to clear	   the upper ownership bit. */	for (i = 0; i < TX_RING_SIZE; i++) {		tx_ring[i].base = 0;		tx_ring[i].status = 0;	}	lp->init_block.tlen_rlen =	    le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);	for (i = 0; i < 6; i++)		lp->init_block.phys_addr[i] = nic->node_addr[i];	lp->init_block.rx_ring = (u32) virt_to_le32desc(&rx_ring[0]);	lp->init_block.tx_ring = (u32) virt_to_le32desc(&tx_ring[0]);	return 0;}/**************************************************************************RESET - Reset adapter***************************************************************************/static void pcnet32_reset(struct nic *nic){	/* put the card in its initial state */	u16 val;	int i;	/* Reset the PCNET32 */	lp->a.reset(ioaddr);	/* switch pcnet32 to 32bit mode */	lp->a.write_bcr(ioaddr, 20, 2);	/* set/reset autoselect bit */	val = lp->a.read_bcr(ioaddr, 2) & ~2;	if (lp->options & PCNET32_PORT_ASEL)		val |= 2;	lp->a.write_bcr(ioaddr, 2, val);	/* handle full duplex setting */	if (lp->full_duplex) {		val = lp->a.read_bcr(ioaddr, 9) & ~3;		if (lp->options & PCNET32_PORT_FD) {			val |= 1;			if (lp->options ==			    (PCNET32_PORT_FD | PCNET32_PORT_AUI))				val |= 2;		} else if (lp->options & PCNET32_PORT_ASEL) {			/* workaround of xSeries250, turn on for 79C975 only */			i = ((lp->a.			      read_csr(ioaddr,				       88) | (lp->a.read_csr(ioaddr,							     89) << 16)) >>			     12) & 0xffff;			if (i == 0x2627)				val |= 3;

⌨️ 快捷键说明

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