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

📄 dm9000.c

📁 2410最新内核linux2.6.22上dm9000网卡驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *   dm9000.c: Version 1.2 03/18/2003 * *         A Davicom DM9000 ISA NIC fast Ethernet driver for Linux. * 	Copyright (C) 1997  Sten Wang * * 	This program is free software; you can redistribute it and/or * 	modify it under the terms of the GNU General Public License * 	as published by the Free Software Foundation; either version 2 * 	of the License, or (at your option) any later version. * * 	This program is distributed in the hope that it will be useful, * 	but WITHOUT ANY WARRANTY; without even the implied warranty of * 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * 	GNU General Public License for more details. * *   (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved. * * V0.11	06/20/2001	REG_0A bit3=1, default enable BP with DA match * 	06/22/2001 	Support DM9801 progrmming * 	 	 	E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000 * 		 	E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200 * 		     		R17 = (R17 & 0xfff0) | NF + 3 * 		 	E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200 * 		     		R17 = (R17 & 0xfff0) | NF * * v1.00               	modify by simon 2001.9.5 *                         change for kernel 2.4.x * * v1.1   11/09/2001      	fix force mode bug * * v1.2   03/18/2003       Weilun Huang <weilun_huang@davicom.com.tw>: * 			Fixed phy reset. * 			Added tx/rx 32 bit mode. * 			Cleaned up for kernel merge. * *        03/03/2004    Sascha Hauer <s.hauer@pengutronix.de> *                      Port to 2.6 kernel * *	  24-Sep-2004   Ben Dooks <ben@simtec.co.uk> *			Cleanup of code to remove ifdefs *			Allowed platform device data to influence access width *			Reformatting areas of code * *        17-Mar-2005   Sascha Hauer <s.hauer@pengutronix.de> *                      * removed 2.4 style module parameters *                      * removed removed unused stat counter and fixed *                        net_device_stats *                      * introduced tx_timeout function *                      * reworked locking * *	  01-Jul-2005   Ben Dooks <ben@simtec.co.uk> *			* fixed spinlock call without pointer *			* ensure spinlock is initialised */#include <linux/module.h>#include <linux/ioport.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/init.h>#include <linux/skbuff.h>#include <linux/spinlock.h>#include <linux/crc32.h>#include <linux/mii.h>#include <linux/dm9000.h>#include <linux/delay.h>#include <linux/platform_device.h>#include <asm/delay.h>#include <asm/irq.h>#include <asm/io.h>#include "dm9000.h"/* Board/System/Debug information/definition ---------------- */#define DM9000_PHY		0x40	/* PHY address 0x01 */#define CARDNAME "dm9000"#define PFX CARDNAME ": "#define DM9000_TIMER_WUT  jiffies+(HZ*2)	/* timer wakeup time : 2 second */#define DM9000_DEBUG 0#if DM9000_DEBUG > 2#define PRINTK3(args...)  printk(CARDNAME ": " args)#else#define PRINTK3(args...)  do { } while(0)#endif#if DM9000_DEBUG > 1#define PRINTK2(args...)  printk(CARDNAME ": " args)#else#define PRINTK2(args...)  do { } while(0)#endif#if DM9000_DEBUG > 0#define PRINTK1(args...)  printk(CARDNAME ": " args)#define PRINTK(args...)   printk(CARDNAME ": " args)#else#define PRINTK1(args...)  do { } while(0)#define PRINTK(args...)   printk(KERN_DEBUG args)#endif/* * Transmit timeout, default 5 seconds. */static int watchdog = 5000;module_param(watchdog, int, 0400);MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");/* Structure/enum declaration ------------------------------- */typedef struct board_info {	void __iomem *io_addr;	/* Register I/O base address */	void __iomem *io_data;	/* Data I/O address */	u16 irq;		/* IRQ */	u16 tx_pkt_cnt;	u16 queue_pkt_len;	u16 queue_start_addr;	u16 dbug_cnt;	u8 io_mode;		/* 0:word, 2:byte */	u8 phy_addr;	void (*inblk)(void __iomem *port, void *data, int length);	void (*outblk)(void __iomem *port, void *data, int length);	void (*dumpblk)(void __iomem *port, int length);	struct resource	*addr_res;   /* resources found */	struct resource *data_res;	struct resource	*addr_req;   /* resources requested */	struct resource *data_req;	struct resource *irq_res;	struct timer_list timer;	struct net_device_stats stats;	unsigned char srom[128];	spinlock_t lock;	struct mii_if_info mii;	u32 msg_enable;} board_info_t;/* function declaration ------------------------------------- */static int dm9000_probe(struct platform_device *);static int dm9000_open(struct net_device *);static int dm9000_start_xmit(struct sk_buff *, struct net_device *);static int dm9000_stop(struct net_device *);static void dm9000_timer(unsigned long);static void dm9000_init_dm9000(struct net_device *);static struct net_device_stats *dm9000_get_stats(struct net_device *);static irqreturn_t dm9000_interrupt(int, void *);static int dm9000_phy_read(struct net_device *dev, int phyaddr_unsused, int reg);static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg,			   int value);static u16 read_srom_word(board_info_t *, int);static void dm9000_rx(struct net_device *);static void dm9000_hash_table(struct net_device *);//#define DM9000_PROGRAM_EEPROM#ifdef DM9000_PROGRAM_EEPROMstatic void program_eeprom(board_info_t * db);#endif/* DM9000 network board routine ---------------------------- */static voiddm9000_reset(board_info_t * db){	PRINTK1("dm9000x: resetting\n");	/* RESET device */	writeb(DM9000_NCR, db->io_addr);	udelay(200);	writeb(NCR_RST, db->io_data);	udelay(200);}/* *   Read a byte from I/O port */static u8ior(board_info_t * db, int reg){	writeb(reg, db->io_addr);	return readb(db->io_data);}/* *   Write a byte to I/O port */static voidiow(board_info_t * db, int reg, int value){	writeb(reg, db->io_addr);	writeb(value, db->io_data);}/* routines for sending block to chip */static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count){	writesb(reg, data, count);}static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count){	writesw(reg, data, (count+1) >> 1);}static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count){	writesl(reg, data, (count+3) >> 2);}/* input block from chip to memory */static void dm9000_inblk_8bit(void __iomem *reg, void *data, int count){	readsb(reg, data, count);}static void dm9000_inblk_16bit(void __iomem *reg, void *data, int count){	readsw(reg, data, (count+1) >> 1);}static void dm9000_inblk_32bit(void __iomem *reg, void *data, int count){	readsl(reg, data, (count+3) >> 2);}/* dump block from chip to null */static void dm9000_dumpblk_8bit(void __iomem *reg, int count){	int i;	int tmp;	for (i = 0; i < count; i++)		tmp = readb(reg);}static void dm9000_dumpblk_16bit(void __iomem *reg, int count){	int i;	int tmp;	count = (count + 1) >> 1;	for (i = 0; i < count; i++)		tmp = readw(reg);}static void dm9000_dumpblk_32bit(void __iomem *reg, int count){	int i;	int tmp;	count = (count + 3) >> 2;	for (i = 0; i < count; i++)		tmp = readl(reg);}/* dm9000_set_io * * select the specified set of io routines to use with the * device */static void dm9000_set_io(struct board_info *db, int byte_width){	/* use the size of the data resource to work out what IO	 * routines we want to use	 */	switch (byte_width) {	case 1:		db->dumpblk = dm9000_dumpblk_8bit;		db->outblk  = dm9000_outblk_8bit;		db->inblk   = dm9000_inblk_8bit;		break;	case 2:		db->dumpblk = dm9000_dumpblk_16bit;		db->outblk  = dm9000_outblk_16bit;		db->inblk   = dm9000_inblk_16bit;		break;	case 3:		printk(KERN_ERR PFX ": 3 byte IO, falling back to 16bit\n");		db->dumpblk = dm9000_dumpblk_16bit;		db->outblk  = dm9000_outblk_16bit;		db->inblk   = dm9000_inblk_16bit;		break;	case 4:	default:		db->dumpblk = dm9000_dumpblk_32bit;		db->outblk  = dm9000_outblk_32bit;		db->inblk   = dm9000_inblk_32bit;		break;	}}/* Our watchdog timed out. Called by the networking layer */static void dm9000_timeout(struct net_device *dev){	board_info_t *db = (board_info_t *) dev->priv;	u8 reg_save;	unsigned long flags;	/* Save previous register address */	reg_save = readb(db->io_addr);	spin_lock_irqsave(&db->lock,flags);	netif_stop_queue(dev);	dm9000_reset(db);	dm9000_init_dm9000(dev);	/* We can accept TX packets again */	dev->trans_start = jiffies;	netif_wake_queue(dev);	/* Restore previous register address */	writeb(reg_save, db->io_addr);	spin_unlock_irqrestore(&db->lock,flags);}#ifdef CONFIG_NET_POLL_CONTROLLER/* *Used by netconsole */static void dm9000_poll_controller(struct net_device *dev){	disable_irq(dev->irq);	dm9000_interrupt(dev->irq,dev);	enable_irq(dev->irq);}#endif/* dm9000_release_board * * release a board, and any mapped resources */static voiddm9000_release_board(struct platform_device *pdev, struct board_info *db){	if (db->data_res == NULL) {		if (db->addr_res != NULL)			release_mem_region((unsigned long)db->io_addr, 4);		return;	}	/* unmap our resources */	iounmap(db->io_addr);	iounmap(db->io_data);	/* release the resources */	if (db->data_req != NULL) {		release_resource(db->data_req);		kfree(db->data_req);	}	if (db->addr_req != NULL) {		release_resource(db->addr_req);		kfree(db->addr_req);	}}#define res_size(_r) (((_r)->end - (_r)->start) + 1)/* * Search DM9000 board, allocate space and register it */static intdm9000_probe(struct platform_device *pdev){	struct dm9000_plat_data *pdata = pdev->dev.platform_data;	struct board_info *db;	/* Point a board information structure */	struct net_device *ndev;	unsigned long base;	int ret = 0;	int iosize;	int i;	u32 id_val;	printk("into dm9000_probe\n");//lzcx	/* Init network device */	ndev = alloc_etherdev(sizeof (struct board_info));	if (!ndev) {		printk("%s: could not allocate device.\n", CARDNAME);		return -ENOMEM;	}	SET_MODULE_OWNER(ndev);	SET_NETDEV_DEV(ndev, &pdev->dev);	PRINTK2("dm9000_probe()");	/* setup board info structure */	db = (struct board_info *) ndev->priv;	memset(db, 0, sizeof (*db));	spin_lock_init(&db->lock);	if (pdev->num_resources < 2) {		ret = -ENODEV;		goto out;	} else if (pdev->num_resources == 2) {		base = pdev->resource[0].start;		if (!request_mem_region(base, 4, ndev->name)) {			ret = -EBUSY;			goto out;		}		ndev->base_addr = base;		ndev->irq = pdev->resource[1].start;		db->io_addr = (void __iomem *)base;		db->io_data = (void __iomem *)(base + 4);	} else {		db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);		db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);		db->irq_res  = platform_get_resource(pdev, IORESOURCE_IRQ, 0);		if (db->addr_res == NULL || db->data_res == NULL ||		    db->irq_res == NULL) {			printk(KERN_ERR PFX "insufficient resources\n");			ret = -ENOENT;			goto out;		}		i = res_size(db->addr_res);		db->addr_req = request_mem_region(db->addr_res->start, i,						  pdev->name);		if (db->addr_req == NULL) {			printk(KERN_ERR PFX "cannot claim address reg area\n");			ret = -EIO;			goto out;		}		db->io_addr = ioremap(db->addr_res->start, i);		if (db->io_addr == NULL) {			printk(KERN_ERR "failed to ioremap address reg\n");			ret = -EINVAL;			goto out;		}		iosize = res_size(db->data_res);		db->data_req = request_mem_region(db->data_res->start, iosize,						  pdev->name);		if (db->data_req == NULL) {			printk(KERN_ERR PFX "cannot claim data reg area\n");			ret = -EIO;			goto out;		}		db->io_data = ioremap(db->data_res->start, iosize);		if (db->io_data == NULL) {			printk(KERN_ERR "failed to ioremap data reg\n");			ret = -EINVAL;			goto out;		}		/* fill in parameters for net-dev structure */		ndev->base_addr = (unsigned long)db->io_addr;		ndev->irq	= db->irq_res->start;		/* ensure at least we have a default set of IO routines */		dm9000_set_io(db, iosize);	}	/* check to see if anything is being over-ridden */	if (pdata != NULL) {		/* check to see if the driver wants to over-ride the		 * default IO width */		if (pdata->flags & DM9000_PLATF_8BITONLY)			dm9000_set_io(db, 1);		if (pdata->flags & DM9000_PLATF_16BITONLY)			dm9000_set_io(db, 2);		if (pdata->flags & DM9000_PLATF_32BITONLY)			dm9000_set_io(db, 4);		/* check to see if there are any IO routine		 * over-rides */		if (pdata->inblk != NULL)			db->inblk = pdata->inblk;		if (pdata->outblk != NULL)			db->outblk = pdata->outblk;		if (pdata->dumpblk != NULL)			db->dumpblk = pdata->dumpblk;	}	dm9000_reset(db);	/* try two times, DM9000 sometimes gets the first read wrong */	for (i = 0; i < 2; i++) {		id_val  = ior(db, DM9000_VIDL);		id_val |= (u32)ior(db, DM9000_VIDH) << 8;		id_val |= (u32)ior(db, DM9000_PIDL) << 16;		id_val |= (u32)ior(db, DM9000_PIDH) << 24;		if (id_val == DM9000_ID)			break;		printk("%s: read wrong id 0x%08x\n", CARDNAME, id_val);	}	if (id_val != DM9000_ID) {		printk("%s: wrong id: 0x%08x\n", CARDNAME, id_val);		goto release;	}	/* from this point we assume that we have found a DM9000 */	/* driver system function */	ether_setup(ndev);	ndev->open		 = &dm9000_open;	ndev->hard_start_xmit    = &dm9000_start_xmit;	ndev->tx_timeout         = &dm9000_timeout;	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);	ndev->stop		 = &dm9000_stop;	ndev->get_stats		 = &dm9000_get_stats;	ndev->set_multicast_list = &dm9000_hash_table;#ifdef CONFIG_NET_POLL_CONTROLLER	ndev->poll_controller	 = &dm9000_poll_controller;#endif#ifdef DM9000_PROGRAM_EEPROM	program_eeprom(db);#endif	db->msg_enable       = NETIF_MSG_LINK;	db->mii.phy_id_mask  = 0x1f;	db->mii.reg_num_mask = 0x1f;	db->mii.force_media  = 0;	db->mii.full_duplex  = 0;	db->mii.dev	     = ndev;	db->mii.mdio_read    = dm9000_phy_read;	db->mii.mdio_write   = dm9000_phy_write;	/* Read SROM content */	for (i = 0; i < 64; i++)		((u16 *) db->srom)[i] = read_srom_word(db, i);	/* Set Node Address */	for (i = 0; i < 6; i++)		ndev->dev_addr[i] = db->srom[i];	if (!is_valid_ether_addr(ndev->dev_addr)) {		/* try reading from mac */		for (i = 0; i < 6; i++)			ndev->dev_addr[i] = ior(db, i+DM9000_PAR);	}	if (!is_valid_ether_addr(ndev->dev_addr))		printk("%s: Invalid ethernet MAC address.  Please "		       "set using ifconfig\n", ndev->name);	platform_set_drvdata(pdev, ndev);	ret = register_netdev(ndev);	if (ret == 0) {		printk("%s: dm9000 at %p,%p IRQ %d MAC: ",		       ndev->name,  db->io_addr, db->io_data, ndev->irq);		for (i = 0; i < 5; i++)			printk("%02x:", ndev->dev_addr[i]);		printk("%02x\n", ndev->dev_addr[5]);	}	return 0; release: out:	printk("%s: not found (%d).\n", CARDNAME, ret);	dm9000_release_board(pdev, db);	free_netdev(ndev);	return ret;}/* *  Open the interface. *  The interface is opened whenever "ifconfig" actives it. */static intdm9000_open(struct net_device *dev){	board_info_t *db = (board_info_t *) dev->priv;	PRINTK2("entering dm9000_open\n");

⌨️ 快捷键说明

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