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

📄 abyss.c

📁 优龙2410linux2.6.8内核源代码
💻 C
字号:
/* *  abyss.c: Network driver for the Madge Smart 16/4 PCI Mk2 token ring card. * *  Written 1999-2000 by Adam Fritzler * *  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: *      - Madge Smart 16/4 PCI Mk2 * *  Maintainer(s): *    AF	Adam Fritzler		mid@auk.cx * *  Modification History: *	30-Dec-99	AF	Split off from the tms380tr driver. *	22-Jan-00	AF	Updated to use indirect read/writes  *	23-Nov-00	JG	New PCI API, cleanups * * *  TODO: *	1. See if we can use MMIO instead of inb/outb/inw/outw *	2. Add support for Mk1 (has AT24 attached to the PCI *		config registers) * */#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 <asm/system.h>#include <asm/io.h>#include <asm/irq.h>#include "tms380tr.h"#include "abyss.h"            /* Madge-specific constants */static char version[] __devinitdata ="abyss.c: v1.02 23/11/2000 by Adam Fritzler\n";#define ABYSS_IO_EXTENT 64static struct pci_device_id abyss_pci_tbl[] = {	{ PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_MK2,	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_TOKEN_RING << 8, 0x00ffffff, },	{ }			/* Terminating entry */};MODULE_DEVICE_TABLE(pci, abyss_pci_tbl);MODULE_LICENSE("GPL");static int abyss_open(struct net_device *dev);static int abyss_close(struct net_device *dev);static void abyss_enable(struct net_device *dev);static int abyss_chipset_init(struct net_device *dev);static void abyss_read_eeprom(struct net_device *dev);static unsigned short abyss_setnselout_pins(struct net_device *dev);static void at24_writedatabyte(unsigned long regaddr, unsigned char byte);static int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr);static int at24_sendcmd(unsigned long regaddr, unsigned char cmd);static unsigned char at24_readdatabit(unsigned long regaddr);static unsigned char at24_readdatabyte(unsigned long regaddr);static int at24_waitforack(unsigned long regaddr);static int at24_waitfornack(unsigned long regaddr);static void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data);static void at24_start(unsigned long regaddr);static unsigned char at24_readb(unsigned long regaddr, unsigned char addr);static unsigned short abyss_sifreadb(struct net_device *dev, unsigned short reg){	return inb(dev->base_addr + reg);}static unsigned short abyss_sifreadw(struct net_device *dev, unsigned short reg){	return inw(dev->base_addr + reg);}static void abyss_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg){	outb(val, dev->base_addr + reg);}static void abyss_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg){	outw(val, dev->base_addr + reg);}static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_id *ent){		static int versionprinted;	struct net_device *dev;	struct net_local *tp;	int i, ret, pci_irq_line;	unsigned long pci_ioaddr;		if (versionprinted++ == 0)		printk("%s", version);	if (pci_enable_device(pdev))		return -EIO;	/* Remove I/O space marker in bit 0. */	pci_irq_line = pdev->irq;	pci_ioaddr = pci_resource_start (pdev, 0);			/* At this point we have found a valid card. */			dev = alloc_trdev(sizeof(struct net_local));	if (!dev)		return -ENOMEM;	SET_MODULE_OWNER(dev);	if (!request_region(pci_ioaddr, ABYSS_IO_EXTENT, dev->name)) {		ret = -EBUSY;		goto err_out_trdev;	}			ret = request_irq(pdev->irq, tms380tr_interrupt, SA_SHIRQ,			  dev->name, dev);	if (ret)		goto err_out_region;			dev->base_addr	= pci_ioaddr;	dev->irq	= pci_irq_line;			printk("%s: Madge Smart 16/4 PCI Mk2 (Abyss)\n", dev->name);	printk("%s:    IO: %#4lx  IRQ: %d\n",	       dev->name, pci_ioaddr, dev->irq);	/*	 * The TMS SIF registers lay 0x10 above the card base address.	 */	dev->base_addr += 0x10;			ret = tmsdev_init(dev, PCI_MAX_ADDRESS, pdev);	if (ret) {		printk("%s: unable to get memory for dev->priv.\n", 		       dev->name);		goto err_out_irq;	}	abyss_read_eeprom(dev);			printk("%s:    Ring Station Address: ", dev->name);	printk("%2.2x", dev->dev_addr[0]);	for (i = 1; i < 6; i++)		printk(":%2.2x", dev->dev_addr[i]);	printk("\n");	tp = netdev_priv(dev);	tp->setnselout = abyss_setnselout_pins;	tp->sifreadb = abyss_sifreadb;	tp->sifreadw = abyss_sifreadw;	tp->sifwriteb = abyss_sifwriteb;	tp->sifwritew = abyss_sifwritew;	memcpy(tp->ProductID, "Madge PCI 16/4 Mk2", PROD_ID_SIZE + 1);			dev->open = abyss_open;	dev->stop = abyss_close;	pci_set_drvdata(pdev, dev);	SET_NETDEV_DEV(dev, &pdev->dev);	ret = register_netdev(dev);	if (ret)		goto err_out_tmsdev;	return 0;err_out_tmsdev:	pci_set_drvdata(pdev, NULL);	tmsdev_term(dev);err_out_irq:	free_irq(pdev->irq, dev);err_out_region:	release_region(pci_ioaddr, ABYSS_IO_EXTENT);err_out_trdev:	free_netdev(dev);	return ret;}static unsigned short abyss_setnselout_pins(struct net_device *dev){	unsigned short val = 0;	struct net_local *tp = netdev_priv(dev);		if(tp->DataRate == SPEED_4)		val |= 0x01;  /* Set 4Mbps */	else		val |= 0x00;  /* Set 16Mbps */		return val;}/* * The following Madge boards should use this code: *   - Smart 16/4 PCI Mk2 (Abyss) *   - Smart 16/4 PCI Mk1 (PCI T) *   - Smart 16/4 Client Plus PnP (Big Apple) *   - Smart 16/4 Cardbus Mk2 * * These access an Atmel AT24 SEEPROM using their glue chip registers.  * */static void at24_writedatabyte(unsigned long regaddr, unsigned char byte){	int i;		for (i = 0; i < 8; i++) {		at24_setlines(regaddr, 0, (byte >> (7-i))&0x01);		at24_setlines(regaddr, 1, (byte >> (7-i))&0x01);		at24_setlines(regaddr, 0, (byte >> (7-i))&0x01);	}}static int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr){	if (at24_sendcmd(regaddr, cmd)) {		at24_writedatabyte(regaddr, addr);		return at24_waitforack(regaddr);	}	return 0;}static int at24_sendcmd(unsigned long regaddr, unsigned char cmd){	int i;		for (i = 0; i < 10; i++) {		at24_start(regaddr);		at24_writedatabyte(regaddr, cmd);		if (at24_waitforack(regaddr))			return 1;	}	return 0;}static unsigned char at24_readdatabit(unsigned long regaddr){	unsigned char val;	at24_setlines(regaddr, 0, 1);	at24_setlines(regaddr, 1, 1);	val = (inb(regaddr) & AT24_DATA)?1:0;	at24_setlines(regaddr, 1, 1);	at24_setlines(regaddr, 0, 1);	return val;}static unsigned char at24_readdatabyte(unsigned long regaddr){	unsigned char data = 0;	int i;		for (i = 0; i < 8; i++) {		data <<= 1;		data |= at24_readdatabit(regaddr);	}	return data;}static int at24_waitforack(unsigned long regaddr){	int i;		for (i = 0; i < 10; i++) {		if ((at24_readdatabit(regaddr) & 0x01) == 0x00)			return 1;	}	return 0;}static int at24_waitfornack(unsigned long regaddr){	int i;	for (i = 0; i < 10; i++) {		if ((at24_readdatabit(regaddr) & 0x01) == 0x01)			return 1;	}	return 0;}static void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data){	unsigned char val = AT24_ENABLE;	if (clock)		val |= AT24_CLOCK;	if (data)		val |= AT24_DATA;	outb(val, regaddr); 	tms380tr_wait(20); /* Very necessary. */}static void at24_start(unsigned long regaddr){	at24_setlines(regaddr, 0, 1);	at24_setlines(regaddr, 1, 1);	at24_setlines(regaddr, 1, 0);	at24_setlines(regaddr, 0, 1);}static unsigned char at24_readb(unsigned long regaddr, unsigned char addr){	unsigned char data = 0xff;		if (at24_sendfullcmd(regaddr, AT24_WRITE, addr)) {		if (at24_sendcmd(regaddr, AT24_READ)) {			data = at24_readdatabyte(regaddr);			if (!at24_waitfornack(regaddr))				data = 0xff;		}	}	return data;}/* * Enable basic functions of the Madge chipset needed * for initialization. */static void abyss_enable(struct net_device *dev){	unsigned char reset_reg;	unsigned long ioaddr;		ioaddr = dev->base_addr;	reset_reg = inb(ioaddr + PCIBM2_RESET_REG);	reset_reg |= PCIBM2_RESET_REG_CHIP_NRES;	outb(reset_reg, ioaddr + PCIBM2_RESET_REG);	tms380tr_wait(100);}/* * Enable the functions of the Madge chipset needed for * full working order.  */static int abyss_chipset_init(struct net_device *dev){	unsigned char reset_reg;	unsigned long ioaddr;		ioaddr = dev->base_addr;		reset_reg = inb(ioaddr + PCIBM2_RESET_REG);		reset_reg |= PCIBM2_RESET_REG_CHIP_NRES;	outb(reset_reg, ioaddr + PCIBM2_RESET_REG);		reset_reg &= ~(PCIBM2_RESET_REG_CHIP_NRES |		       PCIBM2_RESET_REG_FIFO_NRES | 		       PCIBM2_RESET_REG_SIF_NRES);	outb(reset_reg, ioaddr + PCIBM2_RESET_REG);		tms380tr_wait(100);		reset_reg |= PCIBM2_RESET_REG_CHIP_NRES;	outb(reset_reg, ioaddr + PCIBM2_RESET_REG);		reset_reg |= PCIBM2_RESET_REG_SIF_NRES;	outb(reset_reg, ioaddr + PCIBM2_RESET_REG);	reset_reg |= PCIBM2_RESET_REG_FIFO_NRES;	outb(reset_reg, ioaddr + PCIBM2_RESET_REG);	outb(PCIBM2_INT_CONTROL_REG_SINTEN | 	     PCIBM2_INT_CONTROL_REG_PCI_ERR_ENABLE, 	     ioaddr + PCIBM2_INT_CONTROL_REG);  	outb(30, ioaddr + PCIBM2_FIFO_THRESHOLD);		return 0;}static inline void abyss_chipset_close(struct net_device *dev){	unsigned long ioaddr;		ioaddr = dev->base_addr;	outb(0, ioaddr + PCIBM2_RESET_REG);}/* * Read configuration data from the AT24 SEEPROM on Madge cards. * */static void abyss_read_eeprom(struct net_device *dev){	struct net_local *tp;	unsigned long ioaddr;	unsigned short val;	int i;		tp = netdev_priv(dev);	ioaddr = dev->base_addr;		/* Must enable glue chip first */	abyss_enable(dev);		val = at24_readb(ioaddr + PCIBM2_SEEPROM_REG, 			 PCIBM2_SEEPROM_RING_SPEED);	tp->DataRate = val?SPEED_4:SPEED_16; /* set open speed */	printk("%s:    SEEPROM: ring speed: %dMb/sec\n", dev->name, tp->DataRate);		val = at24_readb(ioaddr + PCIBM2_SEEPROM_REG,			 PCIBM2_SEEPROM_RAM_SIZE) * 128;	printk("%s:    SEEPROM: adapter RAM: %dkb\n", dev->name, val);		dev->addr_len = 6;	for (i = 0; i < 6; i++) 		dev->dev_addr[i] = at24_readb(ioaddr + PCIBM2_SEEPROM_REG, 					      PCIBM2_SEEPROM_BIA+i);}static int abyss_open(struct net_device *dev){  	abyss_chipset_init(dev);	tms380tr_open(dev);	return 0;}static int abyss_close(struct net_device *dev){	tms380tr_close(dev);	abyss_chipset_close(dev);	return 0;}static void __devexit abyss_detach (struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata(pdev);		if (!dev)		BUG();	unregister_netdev(dev);	release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT);	free_irq(dev->irq, dev);	tmsdev_term(dev);	free_netdev(dev);	pci_set_drvdata(pdev, NULL);}static struct pci_driver abyss_driver = {	.name		= "abyss",	.id_table	= abyss_pci_tbl,	.probe		= abyss_attach,	.remove		= __devexit_p(abyss_detach),};static int __init abyss_init (void){	int rc = pci_register_driver (&abyss_driver);	if (rc < 0)		return rc;	if (rc == 0) {		pci_unregister_driver (&abyss_driver);		return -ENODEV;	}	return 0;}static void __exit abyss_rmmod (void){	pci_unregister_driver (&abyss_driver);}module_init(abyss_init);module_exit(abyss_rmmod);/* * Local variables: *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c abyss.c" *  alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c abyss.c" *  c-set-style "K&R" *  c-indent-level: 8 *  c-basic-offset: 8 *  tab-width: 8 * End: */

⌨️ 快捷键说明

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