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

📄 com90xx.c

📁 h内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Linux ARCnet driver - COM90xx chipset (memory-mapped buffers) *  * Written 1994-1999 by Avery Pennarun. * Written 1999 by Martin Mares <mj@ucw.cz>. * Derived from skeleton.c by Donald Becker. * * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) *  for sponsoring the further development of this driver. * * ********************** * * The original copyright of skeleton.c was as follows: * * skeleton.c 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 General Public License as * modified by SRC, incorporated herein by reference. * * ********************** * * For more details, see drivers/net/arcnet.c * * ********************** */#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/netdevice.h>#include <asm/io.h>#include <linux/arcdevice.h>#define VERSION "arcnet: COM90xx chipset support\n"/* Define this to speed up the autoprobe by assuming if only one io port and * shmem are left in the list at Stage 5, they must correspond to each * other. * * This is undefined by default because it might not always be true, and the * extra check makes the autoprobe even more careful.  Speed demons can turn * it on - I think it should be fine if you only have one ARCnet card * installed. * * If no ARCnet cards are installed, this delay never happens anyway and thus * the option has no effect. */#undef FAST_PROBE/* Internal function declarations */static int com90xx_found(int ioaddr, int airq, u_long shmem);static void com90xx_command(struct net_device *dev, int command);static int com90xx_status(struct net_device *dev);static void com90xx_setmask(struct net_device *dev, int mask);static int com90xx_reset(struct net_device *dev, int really_reset);static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset,				 void *buf, int count);static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset,				   void *buf, int count);/* Known ARCnet cards */static struct net_device *cards[16];static int numcards;/* Handy defines for ARCnet specific stuff *//* The number of low I/O ports used by the card */#define ARCNET_TOTAL_SIZE	16/* Amount of I/O memory used by the card */#define BUFFER_SIZE (512)#define MIRROR_SIZE (BUFFER_SIZE*4)/* COM 9026 controller chip --> ARCnet register addresses */#define _INTMASK (ioaddr+0)	/* writable */#define _STATUS  (ioaddr+0)	/* readable */#define _COMMAND (ioaddr+1)	/* writable, returns random vals on read (?) */#define _CONFIG  (ioaddr+2)	/* Configuration register */#define _RESET   (ioaddr+8)	/* software reset (on read) */#define _MEMDATA (ioaddr+12)	/* Data port for IO-mapped memory */#define _ADDR_HI (ioaddr+15)	/* Control registers for said */#define _ADDR_LO (ioaddr+14)#undef ASTATUS#undef ACOMMAND#undef AINTMASK#define ASTATUS()	inb(_STATUS)#define ACOMMAND(cmd) 	outb((cmd),_COMMAND)#define AINTMASK(msk)	outb((msk),_INTMASK)static int com90xx_skip_probe __initdata = 0;/* Module parameters */static int io;			/* use the insmod io= irq= shmem= options */static int irq;static int shmem;static char device[9];		/* use eg. device=arc1 to change name */module_param(io, int, 0);module_param(irq, int, 0);module_param(shmem, int, 0);module_param_string(device, device, sizeof(device), 0);static void __init com90xx_probe(void){	int count, status, ioaddr, numprint, airq, openparen = 0;	unsigned long airqmask;	int ports[(0x3f0 - 0x200) / 16 + 1] =	{0};	u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] =	{0};	int numports, numshmems, *port;	u_long *p;	if (!io && !irq && !shmem && !*device && com90xx_skip_probe)		return;	BUGLVL(D_NORMAL) printk(VERSION);	/* set up the arrays where we'll store the possible probe addresses */	numports = numshmems = 0;	if (io)		ports[numports++] = io;	else		for (count = 0x200; count <= 0x3f0; count += 16)			ports[numports++] = count;	if (shmem)		shmems[numshmems++] = shmem;	else		for (count = 0xA0000; count <= 0xFF800; count += 2048)			shmems[numshmems++] = count;	/* Stage 1: abandon any reserved ports, or ones with status==0xFF	 * (empty), and reset any others by reading the reset port.	 */	numprint = -1;	for (port = &ports[0]; port - ports < numports; port++) {		numprint++;		numprint %= 8;		if (!numprint) {			BUGMSG2(D_INIT, "\n");			BUGMSG2(D_INIT, "S1: ");		}		BUGMSG2(D_INIT, "%Xh ", *port);		ioaddr = *port;		if (!request_region(*port, ARCNET_TOTAL_SIZE, "arcnet (90xx)")) {			BUGMSG2(D_INIT_REASONS, "(request_region)\n");			BUGMSG2(D_INIT_REASONS, "S1: ");			BUGLVL(D_INIT_REASONS) numprint = 0;			*port-- = ports[--numports];			continue;		}		if (ASTATUS() == 0xFF) {			BUGMSG2(D_INIT_REASONS, "(empty)\n");			BUGMSG2(D_INIT_REASONS, "S1: ");			BUGLVL(D_INIT_REASONS) numprint = 0;			release_region(*port, ARCNET_TOTAL_SIZE);			*port-- = ports[--numports];			continue;		}		inb(_RESET);	/* begin resetting card */		BUGMSG2(D_INIT_REASONS, "\n");		BUGMSG2(D_INIT_REASONS, "S1: ");		BUGLVL(D_INIT_REASONS) numprint = 0;	}	BUGMSG2(D_INIT, "\n");	if (!numports) {		BUGMSG2(D_NORMAL, "S1: No ARCnet cards found.\n");		return;	}	/* Stage 2: we have now reset any possible ARCnet cards, so we can't	 * do anything until they finish.  If D_INIT, print the list of	 * cards that are left.	 */	numprint = -1;	for (port = &ports[0]; port < ports + numports; port++) {		numprint++;		numprint %= 8;		if (!numprint) {			BUGMSG2(D_INIT, "\n");			BUGMSG2(D_INIT, "S2: ");		}		BUGMSG2(D_INIT, "%Xh ", *port);	}	BUGMSG2(D_INIT, "\n");	mdelay(RESETtime);	/* Stage 3: abandon any shmem addresses that don't have the signature	 * 0xD1 byte in the right place, or are read-only.	 */	numprint = -1;	for (p = &shmems[0]; p < shmems + numshmems; p++) {		u_long ptr = *p;		numprint++;		numprint %= 8;		if (!numprint) {			BUGMSG2(D_INIT, "\n");			BUGMSG2(D_INIT, "S3: ");		}		BUGMSG2(D_INIT, "%lXh ", *p);		if (!request_mem_region(*p, BUFFER_SIZE, "arcnet (90xx)")) {			BUGMSG2(D_INIT_REASONS, "(request_mem_region)\n");			BUGMSG2(D_INIT_REASONS, "Stage 3: ");			BUGLVL(D_INIT_REASONS) numprint = 0;			*p-- = shmems[--numshmems];			continue;		}		if (isa_readb(ptr) != TESTvalue) {			BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n",				isa_readb(ptr), TESTvalue);			BUGMSG2(D_INIT_REASONS, "S3: ");			BUGLVL(D_INIT_REASONS) numprint = 0;			release_mem_region(*p, BUFFER_SIZE);			*p-- = shmems[--numshmems];			continue;		}		/* By writing 0x42 to the TESTvalue location, we also make		 * sure no "mirror" shmem areas show up - if they occur		 * in another pass through this loop, they will be discarded		 * because *cptr != TESTvalue.		 */		isa_writeb(0x42, ptr);		if (isa_readb(ptr) != 0x42) {			BUGMSG2(D_INIT_REASONS, "(read only)\n");			BUGMSG2(D_INIT_REASONS, "S3: ");			release_mem_region(*p, BUFFER_SIZE);			*p-- = shmems[--numshmems];			continue;		}		BUGMSG2(D_INIT_REASONS, "\n");		BUGMSG2(D_INIT_REASONS, "S3: ");		BUGLVL(D_INIT_REASONS) numprint = 0;	}	BUGMSG2(D_INIT, "\n");	if (!numshmems) {		BUGMSG2(D_NORMAL, "S3: No ARCnet cards found.\n");		for (port = &ports[0]; port < ports + numports; port++)			release_region(*port, ARCNET_TOTAL_SIZE);		return;	}	/* Stage 4: something of a dummy, to report the shmems that are	 * still possible after stage 3.	 */	numprint = -1;	for (p = &shmems[0]; p < shmems + numshmems; p++) {		numprint++;		numprint %= 8;		if (!numprint) {			BUGMSG2(D_INIT, "\n");			BUGMSG2(D_INIT, "S4: ");		}		BUGMSG2(D_INIT, "%lXh ", *p);	}	BUGMSG2(D_INIT, "\n");	/* Stage 5: for any ports that have the correct status, can disable	 * the RESET flag, and (if no irq is given) generate an autoirq,	 * register an ARCnet device.	 *	 * Currently, we can only register one device per probe, so quit	 * after the first one is found.	 */	numprint = -1;	for (port = &ports[0]; port < ports + numports; port++) {		int found = 0;		numprint++;		numprint %= 8;		if (!numprint) {			BUGMSG2(D_INIT, "\n");			BUGMSG2(D_INIT, "S5: ");		}		BUGMSG2(D_INIT, "%Xh ", *port);		ioaddr = *port;		status = ASTATUS();		if ((status & 0x9D)		    != (NORXflag | RECONflag | TXFREEflag | RESETflag)) {			BUGMSG2(D_INIT_REASONS, "(status=%Xh)\n", status);			BUGMSG2(D_INIT_REASONS, "S5: ");			BUGLVL(D_INIT_REASONS) numprint = 0;			release_region(*port, ARCNET_TOTAL_SIZE);			*port-- = ports[--numports];			continue;		}		ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);		status = ASTATUS();		if (status & RESETflag) {			BUGMSG2(D_INIT_REASONS, " (eternal reset, status=%Xh)\n",				status);			BUGMSG2(D_INIT_REASONS, "S5: ");			BUGLVL(D_INIT_REASONS) numprint = 0;			release_region(*port, ARCNET_TOTAL_SIZE);			*port-- = ports[--numports];			continue;		}		/* skip this completely if an IRQ was given, because maybe		 * we're on a machine that locks during autoirq!		 */		if (!irq) {			/* if we do this, we're sure to get an IRQ since the			 * card has just reset and the NORXflag is on until			 * we tell it to start receiving.			 */			airqmask = probe_irq_on();			AINTMASK(NORXflag);			udelay(1);			AINTMASK(0);

⌨️ 快捷键说明

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