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

📄 dm9000x.c

📁 linux-2.6.12下的百兆网卡芯片dm9000ae驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *   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 <saschahauer@web.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 */#if defined(MODVERSIONS)#include <linux/modversions.h>#endif#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/version.h>#include <linux/spinlock.h>#include <linux/crc32.h>#include <linux/mii.h>#include <linux/dm9000.h>#include <asm/delay.h>#include <asm/irq.h>#include <asm/io.h>#include "dm9000x.h"#include <asm-arm/arch/irqs.h>#include <asm-arm/arch/hardware.h>#include <asm-arm/arch/regs-gpio.h> /* Board/System/Debug information/definition ---------------- */static void *bwscon;static void *gpfcon;static void *extint0;static void *intmsk;#define BWSCON           (0x48000000)#define GPFCON           (0x56000050)#define EXTINT0           (0x56000088)#define INTMSK           (0x4A000008)#define DM9000_REG00		0x00#define DM9000_REG05		0x30	/* SKIP_CRC/SKIP_LONG */#define DM9000_REG08		0x27#define DM9000_REG09		0x38#define DM9000_REG0A		0xff#define DM9000_REGFF		0x83	/* IMR */#define DM9000_PHY		0x40	/* PHY address 0x01 */#define TRUE			1#define FALSE			0#define CARDNAME "dm9000"#define PFX CARDNAME ": "#define DMFE_TIMER_WUT  jiffies+(HZ*2)	/* timer wakeup time : 2 second */#define DMFE_TX_TIMEOUT (HZ*2)	/* tx packet time-out time 1.5 s" */#define DMFE_DEBUG 0#if DMFE_DEBUG > 2#define PRINTK3(args...)  printk(CARDNAME ": " args)#else#define PRINTK3(args...)  do { } while(0)#endif#if DMFE_DEBUG > 1#define PRINTK2(args...)  printk(CARDNAME ": " args)#else#define PRINTK2(args...)  do { } while(0)#endif#if DMFE_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)#endifenum DM9000_PHY_mode {	DM9000_10MHD = 0,	DM9000_100MHD = 1,	DM9000_10MFD = 4,	DM9000_100MFD = 5,	DM9000_AUTO = 8,	DM9000_1M_HPNA = 0x10};/* Structure/enum declaration ------------------------------- */typedef struct board_info {	u32 runt_length_counter;	/* counter: RX length < 64byte */	u32 long_length_counter;	/* counter: RX length > 1514byte */	u32 reset_counter;	/* counter: RESET */	u32 reset_tx_timeout;	/* RESET caused by TX Timeout */	u32 reset_rx_status;	/* RESET caused by RX Statsus wrong */	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 reg0, reg5, reg8, reg9, rega;	/* registers saved */	u8 op_mode;		/* PHY operation mode */	u8 io_mode;		/* 0:word, 2:byte */	u8 phy_addr;	u8 device_wait_reset;	/* device state */	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;/* Global variable declaration ----------------------------- */static int dmfe_debug = 0;/* For module input parameter */static int debug = 0;static int mode = DM9000_AUTO;static int media_mode = DM9000_AUTO;static u8 reg5 = DM9000_REG05;static u8 reg8 = DM9000_REG08;static u8 reg9 = DM9000_REG09;static u8 rega = DM9000_REG0A;static u8 nfloor = 0;#ifdef CONFIG_MX1_SCB9328#include <asm/arch/hardware.h>#include <asm/arch/irqs.h>#include <asm/arch/scb9328.h>#elsestatic u8 irqline = 3;#endif/* function declaration ------------------------------------- */static int dmfe_probe(struct device *);static int dmfe_open(struct net_device *);static int dmfe_start_xmit(struct sk_buff *, struct net_device *);static int dmfe_stop(struct net_device *);static int dmfe_do_ioctl(struct net_device *, struct ifreq *, int);static void dmfe_timer(unsigned long);static void dmfe_init_dm9000(struct net_device *);static struct net_device_stats *dmfe_get_stats(struct net_device *);static irqreturn_t dmfe_interrupt(int, void *, struct pt_regs *);static int dmfe_phy_read(struct net_device *dev, int phyaddr_unsused, int reg);static void dmfe_phy_write(struct net_device *dev, int phyaddr_unused, int reg,			   int value);static u16 read_srom_word(board_info_t *, int);static void dmfe_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 voiddmfe_reset(board_info_t * db){	PRINTK1("dm9000x: resetting\n");	/* RESET device */	writeb(DMFE_NCR, db->io_addr);	udelay(200);		/* delay 100us */	writeb(NCR_RST, db->io_data);	udelay(200);		/* delay 100us */}/* *   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+1);}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);}/* dmfe_set_io * * select the specified set of io routines to use with the * device*/static void dmfe_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;	}}/* dmfe_release_board * * release a board, and any mapped resources*/static voiddmfe_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_res != NULL) {		release_resource(db->data_req);		kfree(db->addr_req);	}}#define res_size(_r) (((_r)->end - (_r)->start) + 1)/*  Search DM9000 board, allocate space and register it*/static intdmfe_probe(struct device *dev){	struct platform_device *pdev = to_platform_device(dev);	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;	unsigned char ne_def_eth_mac_addr[]={0x00,0x12,0x34,0x56,0x80,0x49};	bwscon=ioremap_nocache(BWSCON,0x0000004);	gpfcon=ioremap_nocache(GPFCON,0x0000004);	extint0=ioremap_nocache(EXTINT0,0x0000004);	intmsk=ioremap_nocache(INTMSK,0x0000004);	               	writel(readl(bwscon)|0xc0000,bwscon);	writel( (readl(gpfcon) & ~(0x3 << 14)) | (0x2 << 14), gpfcon); 	writel( readl(gpfcon) | (0x1 << 7), gpfcon); // Disable pull-up	writel( (readl(extint0) & ~(0xf << 28)) | (0x4 << 28), extint0); //rising edge	writel( (readl(intmsk))  & ~0x80, intmsk);   	printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);	/* 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, dev);	PRINTK2("dmfe_probe()");	/* setup board info structure */	db = (struct board_info *) ndev->priv;	memset(db, 0, sizeof (*db));	if (pdev->num_resources < 2) {		ret = -ENODEV;		goto out;	}	switch (pdev->num_resources) {	case 2:		base = pdev->resource[0].start;		if (!request_mem_region(base, 4, ndev->name)) {

⌨️ 快捷键说明

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