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

📄 skisa.c

📁 linux-2.6.15.6
💻 C
字号:
/* *  skisa.c: A network driver for SK-NET TMS380-based ISA token ring cards. * *  Based on tmspci written 1999 by Adam Fritzler *   *  Written 2000 by Jochen Friedrich *  Dedicated to my girlfriend Steffi Bopp * *  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: *	- SysKonnect TR4/16(+) ISA	(SK-4190) * *  Maintainer(s): *    AF        Adam Fritzler           mid@auk.cx *    JF	Jochen Friedrich	jochen@scram.de * *  Modification History: *	14-Jan-01	JF	Created *	28-Oct-02	JF	Fixed probe of card for static compilation. *				Fixed module init to not make hotplug go wild. *	09-Nov-02	JF	Fixed early bail out on out of memory *				situations if multiple cards are found. *				Cleaned up some unnecessary console SPAM. *	09-Dec-02	JF	Fixed module reference counting. *	02-Jan-03	JF	Renamed to skisa.c * */static const char version[] = "skisa.c: v1.03 09/12/2002 by Jochen Friedrich\n";#include <linux/module.h>#include <linux/kernel.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 SK_ISA_IO_EXTENT 32/* A zero-terminated list of I/O addresses to be probed. */static unsigned int portlist[] __initdata = {	0x0A20, 0x1A20, 0x0B20, 0x1B20, 0x0980, 0x1980, 0x0900, 0x1900,// SK	0};/* A zero-terminated list of IRQs to be probed.  * Used again after initial probe for sktr_chipset_init, called from sktr_open. */static const unsigned short irqlist[] = {	3, 5, 9, 10, 11, 12, 15,	0};/* A zero-terminated list of DMAs to be probed. */static int dmalist[] __initdata = {	5, 6, 7,	0};static char isa_cardname[] = "SK NET TR 4/16 ISA\0";static u64 dma_mask = ISA_MAX_ADDRESS;static int sk_isa_open(struct net_device *dev);static void sk_isa_read_eeprom(struct net_device *dev);static unsigned short sk_isa_setnselout_pins(struct net_device *dev);static unsigned short sk_isa_sifreadb(struct net_device *dev, unsigned short reg){	return inb(dev->base_addr + reg);}static unsigned short sk_isa_sifreadw(struct net_device *dev, unsigned short reg){	return inw(dev->base_addr + reg);}static void sk_isa_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg){	outb(val, dev->base_addr + reg);}static void sk_isa_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg){	outw(val, dev->base_addr + reg);}static int __init sk_isa_probe1(struct net_device *dev, int ioaddr){	unsigned char old, chk1, chk2;	if (!request_region(ioaddr, SK_ISA_IO_EXTENT, isa_cardname))		return -ENODEV;	old = inb(ioaddr + SIFADR);	/* Get the old SIFADR value */	chk1 = 0;	/* Begin with check value 0 */	do {		/* Write new SIFADR value */		outb(chk1, ioaddr + SIFADR);		/* Read, invert and write */		chk2 = inb(ioaddr + SIFADD);		chk2 ^= 0x0FE;		outb(chk2, ioaddr + SIFADR);		/* Read, invert and compare */		chk2 = inb(ioaddr + SIFADD);		chk2 ^= 0x0FE;		if(chk1 != chk2) {			release_region(ioaddr, SK_ISA_IO_EXTENT);			return -ENODEV;		}		chk1 -= 2;	} while(chk1 != 0);	/* Repeat 128 times (all byte values) */    	/* Restore the SIFADR value */	outb(old, ioaddr + SIFADR);	dev->base_addr = ioaddr;	return 0;}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 = sk_isa_probe1(dev, dev->base_addr);	else {		for (port = portlist; *port; port++) {			err = sk_isa_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; 			sk_isa_read_eeprom(dev);	printk(KERN_DEBUG "skisa.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 = sk_isa_setnselout_pins;			tp->sifreadb = sk_isa_sifreadb;	tp->sifreadw = sk_isa_sifreadw;	tp->sifwriteb = sk_isa_sifwriteb;	tp->sifwritew = sk_isa_sifwritew;		memcpy(tp->ProductID, isa_cardname, PROD_ID_SIZE + 1);	tp->tmspriv = NULL;	dev->open = sk_isa_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, 				isa_cardname, dev))				break;                }		                if(irqlist[j] == 0)                {                        printk(KERN_INFO "skisa.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 "skisa.c: Illegal IRQ %d specified\n",				dev->irq);			goto out3;		}		if (request_irq(dev->irq, tms380tr_interrupt, 0, 			isa_cardname, dev))		{                        printk(KERN_INFO "skisa.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, isa_cardname))				break;		}		if(dmalist[j] == 0)		{			printk(KERN_INFO "skisa.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 "skisa.c: Illegal DMA %d specified\n",				dev->dma);			goto out2;		}		if (request_dma(dev->dma, isa_cardname))		{                        printk(KERN_INFO "skisa.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, SK_ISA_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 sk_isa_read_eeprom(struct net_device *dev){	int i;		/* Address: 0000:0000 */	sk_isa_sifwritew(dev, 0, SIFADX);	sk_isa_sifwritew(dev, 0, SIFADR);			/* Read six byte MAC address data */	dev->addr_len = 6;	for(i = 0; i < 6; i++)		dev->dev_addr[i] = sk_isa_sifreadw(dev, SIFINC) >> 8;}unsigned short sk_isa_setnselout_pins(struct net_device *dev){	return 0;}static int sk_isa_open(struct net_device *dev){  	struct net_local *tp = netdev_priv(dev);	unsigned short val = 0;	unsigned short oldval;	int i;	val = 0;	for(i = 0; irqlist[i] != 0; i++)	{		if(irqlist[i] == dev->irq)			break;	}	val |= CYCLE_TIME << 2;	val |= i << 4;	i = dev->dma - 5;	val |= i;	if(tp->DataRate == SPEED_4)		val |= LINE_SPEED_BIT;	else		val &= ~LINE_SPEED_BIT;	oldval = sk_isa_sifreadb(dev, POSREG);	/* Leave cycle bits alone */	oldval |= 0xf3;	val &= oldval;	sk_isa_sifwriteb(dev, val, POSREG);	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 *sk_isa_dev[ISATR_MAX_ADAPTERS];static struct platform_driver sk_isa_driver = {	.driver		= {		.name	= "skisa",	},};static int __init sk_isa_init(void){	struct net_device *dev;	struct platform_device *pdev;	int i, num = 0, err = 0;	err = platform_driver_register(&sk_isa_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("skisa",			i, NULL, 0);		err = setup_card(dev, &pdev->dev);		if (!err) {			sk_isa_dev[i] = pdev;			platform_set_drvdata(sk_isa_dev[i], dev);			++num;		} else {			platform_device_unregister(pdev);			free_netdev(dev);		}	}	printk(KERN_NOTICE "skisa.c: %d cards found.\n", num);	/* Probe for cards. */	if (num == 0) {		printk(KERN_NOTICE "skisa.c: No cards found.\n");		return (-ENODEV);	}	return (0);}static void __exit sk_isa_cleanup(void){	struct net_device *dev;	int i;	for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {		struct platform_device *pdev = sk_isa_dev[i];		if (!pdev)			continue;		dev = platform_get_drvdata(pdev);		unregister_netdev(dev);		release_region(dev->base_addr, SK_ISA_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(&sk_isa_driver);}module_init(sk_isa_init);module_exit(sk_isa_cleanup);

⌨️ 快捷键说明

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