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

📄 proteon.c

📁 linux-2.6.15.6
💻 C
字号:
/* *  proteon.c: A network driver for Proteon ISA token ring cards. * *  Based on tmspci written 1999 by Adam Fritzler *   *  Written 2003 by Jochen Friedrich * *  This software may be used and distributed according to the terms *  of the GNU General Public License, incorporated herein by reference. * *  This driver module supports the following cards: *	- Proteon 1392, 1392+ * *  Maintainer(s): *    AF        Adam Fritzler           mid@auk.cx *    JF	Jochen Friedrich	jochen@scram.de * *  Modification History: *	02-Jan-03	JF	Created * */static const char version[] = "proteon.c: v1.00 02/01/2003 by Jochen Friedrich\n";#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/netdevice.h>#include <linux/trdevice.h>#include <linux/platform_device.h>#include <asm/system.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/pci.h>#include <asm/dma.h>#include "tms380tr.h"#define PROTEON_IO_EXTENT 32/* A zero-terminated list of I/O addresses to be probed. */static unsigned int portlist[] __initdata = {	0x0A20, 0x0E20, 0x1A20, 0x1E20, 0x2A20, 0x2E20, 0x3A20, 0x3E20,// Prot.	0x4A20, 0x4E20, 0x5A20, 0x5E20, 0x6A20, 0x6E20, 0x7A20, 0x7E20,// Prot.	0x8A20, 0x8E20, 0x9A20, 0x9E20, 0xAA20, 0xAE20, 0xBA20, 0xBE20,// Prot.	0xCA20, 0xCE20, 0xDA20, 0xDE20, 0xEA20, 0xEE20, 0xFA20, 0xFE20,// Prot.	0};/* A zero-terminated list of IRQs to be probed. */static unsigned short irqlist[] = {	7, 6, 5, 4, 3, 12, 11, 10, 9,	0};/* A zero-terminated list of DMAs to be probed. */static int dmalist[] __initdata = {	5, 6, 7,	0};static char cardname[] = "Proteon 1392\0";static u64 dma_mask = ISA_MAX_ADDRESS;static int proteon_open(struct net_device *dev);static void proteon_read_eeprom(struct net_device *dev);static unsigned short proteon_setnselout_pins(struct net_device *dev);static unsigned short proteon_sifreadb(struct net_device *dev, unsigned short reg){	return inb(dev->base_addr + reg);}static unsigned short proteon_sifreadw(struct net_device *dev, unsigned short reg){	return inw(dev->base_addr + reg);}static void proteon_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg){	outb(val, dev->base_addr + reg);}static void proteon_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg){	outw(val, dev->base_addr + reg);}static int __init proteon_probe1(struct net_device *dev, int ioaddr){	unsigned char chk1, chk2;	int i;	if (!request_region(ioaddr, PROTEON_IO_EXTENT, cardname))		return -ENODEV;			chk1 = inb(ioaddr + 0x1f);      /* Get Proteon ID reg 1 */	if (chk1 != 0x1f) 		goto nodev;	chk1 = inb(ioaddr + 0x1e) & 0x07;       /* Get Proteon ID reg 0 */	for (i=0; i<16; i++) {		chk2 = inb(ioaddr + 0x1e) & 0x07;		if (((chk1 + 1) & 0x07) != chk2)			goto nodev;		chk1 = chk2;	}	dev->base_addr = ioaddr;	return (0);nodev:	release_region(ioaddr, PROTEON_IO_EXTENT); 	return -ENODEV;}static int __init setup_card(struct net_device *dev, struct device *pdev){	struct net_local *tp;        static int versionprinted;	const unsigned *port;	int j,err = 0;	if (!dev)		return -ENOMEM;	SET_MODULE_OWNER(dev);	if (dev->base_addr)	/* probe specific location */		err = proteon_probe1(dev, dev->base_addr);	else {		for (port = portlist; *port; port++) {			err = proteon_probe1(dev, *port);			if (!err)				break;		}	}	if (err)		goto out5;	/* At this point we have found a valid card. */	if (versionprinted++ == 0)		printk(KERN_DEBUG "%s", version);	err = -EIO;	pdev->dma_mask = &dma_mask;	if (tmsdev_init(dev, pdev))		goto out4;	dev->base_addr &= ~3; 			proteon_read_eeprom(dev);	printk(KERN_DEBUG "proteon.c:    Ring Station Address: ");	printk("%2.2x", dev->dev_addr[0]);	for (j = 1; j < 6; j++)		printk(":%2.2x", dev->dev_addr[j]);	printk("\n");			tp = netdev_priv(dev);	tp->setnselout = proteon_setnselout_pins;			tp->sifreadb = proteon_sifreadb;	tp->sifreadw = proteon_sifreadw;	tp->sifwriteb = proteon_sifwriteb;	tp->sifwritew = proteon_sifwritew;		memcpy(tp->ProductID, cardname, PROD_ID_SIZE + 1);	tp->tmspriv = NULL;	dev->open = proteon_open;	dev->stop = tms380tr_close;	if (dev->irq == 0)	{		for(j = 0; irqlist[j] != 0; j++)		{			dev->irq = irqlist[j];			if (!request_irq(dev->irq, tms380tr_interrupt, 0, 				cardname, dev))				break;                }		                if(irqlist[j] == 0)                {                        printk(KERN_INFO "proteon.c: AutoSelect no IRQ available\n");			goto out3;		}	}	else	{		for(j = 0; irqlist[j] != 0; j++)			if (irqlist[j] == dev->irq)				break;		if (irqlist[j] == 0)		{			printk(KERN_INFO "proteon.c: Illegal IRQ %d specified\n",				dev->irq);			goto out3;		}		if (request_irq(dev->irq, tms380tr_interrupt, 0, 			cardname, dev))		{                        printk(KERN_INFO "proteon.c: Selected IRQ %d not available\n",				dev->irq);			goto out3;		}	}	if (dev->dma == 0)	{		for(j = 0; dmalist[j] != 0; j++)		{			dev->dma = dmalist[j];                        if (!request_dma(dev->dma, cardname))				break;		}		if(dmalist[j] == 0)		{			printk(KERN_INFO "proteon.c: AutoSelect no DMA available\n");			goto out2;		}	}	else	{		for(j = 0; dmalist[j] != 0; j++)			if (dmalist[j] == dev->dma)				break;		if (dmalist[j] == 0)		{                        printk(KERN_INFO "proteon.c: Illegal DMA %d specified\n",				dev->dma);			goto out2;		}		if (request_dma(dev->dma, cardname))		{                        printk(KERN_INFO "proteon.c: Selected DMA %d not available\n",				dev->dma);			goto out2;		}	}	err = register_netdev(dev);	if (err)		goto out;	printk(KERN_DEBUG "%s:    IO: %#4lx  IRQ: %d  DMA: %d\n",	       dev->name, dev->base_addr, dev->irq, dev->dma);	return 0;out:	free_dma(dev->dma);out2:	free_irq(dev->irq, dev);out3:	tmsdev_term(dev);out4:	release_region(dev->base_addr, PROTEON_IO_EXTENT);out5:	return err;}/* * Reads MAC address from adapter RAM, which should've read it from * the onboard ROM.   * * Calling this on a board that does not support it can be a very * dangerous thing.  The Madge board, for instance, will lock your * machine hard when this is called.  Luckily, its supported in a * separate driver.  --ASF */static void proteon_read_eeprom(struct net_device *dev){	int i;		/* Address: 0000:0000 */	proteon_sifwritew(dev, 0, SIFADX);	proteon_sifwritew(dev, 0, SIFADR);			/* Read six byte MAC address data */	dev->addr_len = 6;	for(i = 0; i < 6; i++)		dev->dev_addr[i] = proteon_sifreadw(dev, SIFINC) >> 8;}unsigned short proteon_setnselout_pins(struct net_device *dev){	return 0;}static int proteon_open(struct net_device *dev){  	struct net_local *tp = netdev_priv(dev);	unsigned short val = 0;	int i;	/* Proteon reset sequence */	outb(0, dev->base_addr + 0x11);	mdelay(20);	outb(0x04, dev->base_addr + 0x11);	mdelay(20);	outb(0, dev->base_addr + 0x11);	mdelay(100);	/* set control/status reg */	val = inb(dev->base_addr + 0x11);	val |= 0x78;	val &= 0xf9;	if(tp->DataRate == SPEED_4)		val |= 0x20;	else		val &= ~0x20;	outb(val, dev->base_addr + 0x11);	outb(0xff, dev->base_addr + 0x12);	for(i = 0; irqlist[i] != 0; i++)	{		if(irqlist[i] == dev->irq)			break;	}	val = i;	i = (7 - dev->dma) << 4;	val |= i;	outb(val, dev->base_addr + 0x13);	return tms380tr_open(dev);}#define ISATR_MAX_ADAPTERS 3static int io[ISATR_MAX_ADAPTERS];static int irq[ISATR_MAX_ADAPTERS];static int dma[ISATR_MAX_ADAPTERS];MODULE_LICENSE("GPL");module_param_array(io, int, NULL, 0);module_param_array(irq, int, NULL, 0);module_param_array(dma, int, NULL, 0);static struct platform_device *proteon_dev[ISATR_MAX_ADAPTERS];static struct platform_driver proteon_driver = {	.driver		= {		.name	= "proteon",	},};static int __init proteon_init(void){	struct net_device *dev;	struct platform_device *pdev;	int i, num = 0, err = 0;	err = platform_driver_register(&proteon_driver);	if (err)		return err;	for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {		dev = alloc_trdev(sizeof(struct net_local));		if (!dev)			continue;		dev->base_addr = io[i];		dev->irq = irq[i];		dev->dma = dma[i];		pdev = platform_device_register_simple("proteon",			i, NULL, 0);		err = setup_card(dev, &pdev->dev);		if (!err) {			proteon_dev[i] = pdev;			platform_set_drvdata(pdev, dev);			++num;		} else {			platform_device_unregister(pdev);			free_netdev(dev);		}	}	printk(KERN_NOTICE "proteon.c: %d cards found.\n", num);	/* Probe for cards. */	if (num == 0) {		printk(KERN_NOTICE "proteon.c: No cards found.\n");		return (-ENODEV);	}	return (0);}static void __exit proteon_cleanup(void){	struct net_device *dev;	int i;	for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {		struct platform_device *pdev = proteon_dev[i];				if (!pdev)			continue;		dev = platform_get_drvdata(pdev);		unregister_netdev(dev);		release_region(dev->base_addr, PROTEON_IO_EXTENT);		free_irq(dev->irq, dev);		free_dma(dev->dma);		tmsdev_term(dev);		free_netdev(dev);		platform_set_drvdata(pdev, NULL);		platform_device_unregister(pdev);	}	platform_driver_unregister(&proteon_driver);}module_init(proteon_init);module_exit(proteon_cleanup);

⌨️ 快捷键说明

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