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

📄 fmv18x.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* fmv18x.c: A network device driver for the Fujitsu FMV-181/182/183/184.	Original: at1700.c (1993-94 by Donald Becker).		Copyright 1993 United States Government as represented by the		Director, National Security Agency.		The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O		Center of Excellence in Space Data and Information Sciences		   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771	Modified by Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)		Copyright 1994 Fujitsu Laboratories Ltd.	Special thanks to:		Masayoshi UTAKA (utaka@ace.yk.fujitsu.co.jp)			for testing this driver.		H. NEGISHI (agy, negishi@sun45.psd.cs.fujitsu.co.jp)			for suggestion of some program modification.		Masahiro SEKIGUCHI <seki@sysrap.cs.fujitsu.co.jp>			for suggestion of some program modification.		Kazutoshi MORIOKA (morioka@aurora.oaks.cs.fujitsu.co.jp)			for testing this driver.	This software may be used and distributed according to the terms	of the GNU Public License, incorporated herein by reference.	This is a device driver for the Fujitsu FMV-181/182/183/184, which	is a straight-forward Fujitsu MB86965 implementation.  Sources:    at1700.c    The Fujitsu MB86965 datasheet.    The Fujitsu FMV-181/182 user's guide*/static const char *version =	"fmv18x.c:v2.2.0 09/24/98  Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)\n";#include <linux/module.h>#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 <linux/init.h>#include <asm/system.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/dma.h>#include <linux/errno.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/delay.h>static int fmv18x_probe_list[] __initdata ={0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0};/* use 0 for production, 1 for verification, >2 for debug */#ifndef NET_DEBUG#define NET_DEBUG 1#endifstatic unsigned int net_debug = NET_DEBUG;typedef unsigned char uchar;/* Information that need to be kept for each board. */struct net_local {	struct net_device_stats stats;	long open_time;				/* Useless example local info. */	uint tx_started:1;			/* Number of packet on the Tx queue. */	uint tx_queue_ready:1;		/* Tx queue is ready to be sent. */	uint rx_started:1;			/* Packets are Rxing. */	uchar tx_queue;				/* Number of packet on the Tx queue. */	ushort tx_queue_len;		/* Current length of the Tx queue. */};/* Offsets from the base address. */#define STATUS			0#define TX_STATUS		0#define RX_STATUS		1#define TX_INTR			2		/* Bit-mapped interrupt enable registers. */#define RX_INTR			3#define TX_MODE			4#define RX_MODE			5#define CONFIG_0		6		/* Misc. configuration settings. */#define CONFIG_1		7/* Run-time register bank 2 definitions. */#define DATAPORT		8		/* Word-wide DMA or programmed-I/O dataport. */#define TX_START		10#define COL16CNTL		11		/* Controll Reg for 16 collisions */#define MODE13			13/* Fujitsu FMV-18x Card Configuration */#define	FJ_STATUS0		0x10#define	FJ_STATUS1		0x11#define	FJ_CONFIG0		0x12#define	FJ_CONFIG1		0x13#define	FJ_MACADDR		0x14	/* 0x14 - 0x19 */#define	FJ_BUFCNTL		0x1A#define	FJ_BUFDATA		0x1C#define FMV18X_IO_EXTENT	32/* Index to functions, as function prototypes. */extern int fmv18x_probe(struct device *dev);static int fmv18x_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 irq, void *dev_id, struct pt_regs *regs);static void net_rx(struct device *dev);static int net_close(struct device *dev);static struct net_device_stats *net_get_stats(struct device *dev);static void set_multicast_list(struct device *dev);/* 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, allocate space for the device and return success   (detachable devices only).   */#ifdef HAVE_DEVLIST/* Support for an alternate probe manager, which will eliminate the   boilerplate below. */struct netdev_entry fmv18x_drv ={"fmv18x", fmv18x_probe1, FMV18X_IO_EXTENT, fmv18x_probe_list};#else__initfunc(intfmv18x_probe(struct device *dev)){	int i;	int base_addr = dev ? dev->base_addr : 0;	if (base_addr > 0x1ff)		/* Check a single specified location. */		return fmv18x_probe1(dev, base_addr);	else if (base_addr != 0)	/* Don't probe at all. */		return ENXIO;	for (i = 0; fmv18x_probe_list[i]; i++) {		int ioaddr = fmv18x_probe_list[i]; 		if (check_region(ioaddr, FMV18X_IO_EXTENT))			continue;		if (fmv18x_probe1(dev, ioaddr) == 0)			return 0;	}	return ENODEV;}#endif/* The Fujitsu datasheet suggests that the NIC be probed for by checking its   "signature", the default bit pattern after a reset.  This *doesn't* work --   there is no way to reset the bus interface without a complete power-cycle!   It turns out that ATI came to the same conclusion I did: the only thing   that can be done is checking a few bits and then diving right into MAC   address check. */__initfunc(int fmv18x_probe1(struct device *dev, short ioaddr)){	char irqmap[4] = {3, 7, 10, 15};	char irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};	unsigned int i, irq;	/* Resetting the chip doesn't reset the ISA interface, so don't bother.	   That means we have to be careful with the register values we probe for.	   */	/* Check I/O address configuration and Fujitsu vendor code */	if (inb(ioaddr+FJ_MACADDR  ) != 0x00	||  inb(ioaddr+FJ_MACADDR+1) != 0x00	||  inb(ioaddr+FJ_MACADDR+2) != 0x0e)		return -ENODEV;	/* Check PnP mode for FMV-183/184/183A/184A. */	/* This PnP routine is very poor. IO and IRQ should be known. */	if (inb(ioaddr + FJ_STATUS1) & 0x20) {		irq = dev->irq;		for (i = 0; i < 8; i++) {			if (irq == irqmap_pnp[i])				break;		}		if (i == 8)			return -ENODEV;	} else {		if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr)			return -ENODEV;		irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];	}	/* Snarf the interrupt vector now. */	if (request_irq(irq, &net_interrupt, 0, "fmv18x", dev)) {		printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on"				"IRQ %d.\n", ioaddr, irq);		return EAGAIN;	}	/* Allocate a new 'dev' if needed. */	if (dev == NULL)		dev = init_etherdev(0, sizeof(struct net_local));	/* Grab the region so that we can find another board if the IRQ request	   fails. */ 	request_region(ioaddr, FMV18X_IO_EXTENT, "fmv18x");	printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name,		   ioaddr, irq);	dev->base_addr = ioaddr;	dev->irq = irq;	for(i = 0; i < 6; i++) {		unsigned char val = inb(ioaddr + FJ_MACADDR + i);		printk("%02x", val);		dev->dev_addr[i] = val;	}	/* "FJ_STATUS0" 12 bit 0x0400 means use regular 100 ohm 10baseT signals,	   rather than 150 ohm shielded twisted pair compensation.	   0x0000 == auto-sense the interface	   0x0800 == use TP interface	   0x1800 == use coax interface	   */	{		const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2/5"};		ushort setup_value = inb(ioaddr + FJ_STATUS0);		switch( setup_value & 0x07 ){		case 0x01 /* 10base5 */:		case 0x02 /* 10base2 */: dev->if_port = 0x18; break;		case 0x04 /* 10baseT */: dev->if_port = 0x08; break;		default /* auto-sense*/: dev->if_port = 0x00; break;		}		printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);	}	/* Initialize LAN Controller and LAN Card */	outb(0xda, ioaddr + CONFIG_0);	 /* Initialize LAN Controller */	outb(0x00, ioaddr + CONFIG_1);	 /* Stand by mode */	outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */	outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure (TAMIYA) */	/* wait for a while */	udelay(200);	/* Set the station address in bank zero. */	outb(0x00, ioaddr + CONFIG_1);	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(0x04, ioaddr + CONFIG_1);	for (i = 0; i < 8; i++)		outb(0x00, ioaddr + 8 + i);	/* Switch to bank 2 and lock our I/O address. */	outb(0x08, ioaddr + CONFIG_1);	outb(dev->if_port, ioaddr + MODE13);	outb(0x00, ioaddr + COL16CNTL);	if (net_debug)		printk(version);	/* Initialize the device structure. */	dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);	if (dev->priv == NULL)		return -ENOMEM;	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;	dev->set_multicast_list = &set_multicast_list;	/* Fill in the fields of 'dev' with ethernet-generic values. */	ether_setup(dev);	return 0;}static int net_open(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	int ioaddr = dev->base_addr;	/* Set the configuration register 0 to 32K 100ns. byte-wide memory,	   16 bit bus access, and two 4K Tx, enable the Rx and Tx. */	outb(0x5a, ioaddr + CONFIG_0);	/* Powerup and switch to register bank 2 for the run-time registers. */	outb(0xe8, ioaddr + CONFIG_1);	lp->tx_started = 0;	lp->tx_queue_ready = 1;	lp->rx_started = 0;	lp->tx_queue = 0;	lp->tx_queue_len = 0;	/* Clear Tx and Rx Status */	outb(0xff, ioaddr + TX_STATUS);	outb(0xff, ioaddr + RX_STATUS);	lp->open_time = jiffies;	dev->tbusy = 0;	dev->interrupt = 0;	dev->start = 1;	/* Enable the IRQ of the LAN Card */	outb(0x80, ioaddr + FJ_CONFIG1);	/* Enable both Tx and Rx interrupts */	outw(0x8182, ioaddr+TX_INTR);	MOD_INC_USE_COUNT;	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,			   htons(inw(ioaddr + TX_STATUS)),			   inb(ioaddr + TX_STATUS) & 0x80			   ? "IRQ conflict" : "network cable problem");		printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",

⌨️ 快捷键说明

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