📄 dm9000.c
字号:
/* * dm9000.c: Version 1.2 03/18/2003------yangdk modified for YLP2440,2008,5.5 * * 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"//yangdk------>#include <asm-arm/arch/irqs.h>#include <asm-arm/arch/hardware.h>#include <asm-arm/arch/regs-gpio.h>//yangdk<------/* 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#ifdef CONFIG_BLACKFIN#define readsb insb#define readsw insw#define readsl insl#define writesb outsb#define writesw outsw#define writesl outsl#define DM9000_IRQ_FLAGS (IRQF_SHARED | IRQF_TRIGGER_HIGH)#else#define DM9000_IRQ_FLAGS IRQF_SHARED#endif#define DM9000_IRQ IRQ_EINT3/* * 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; 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 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; unsigned char ne_def_eth_mac_addr[]={0x00,0x12,0x34,0x56,0x80,0x49};//yangdk /* Init network device */ ndev = alloc_etherdev(sizeof (struct board_info)); if (!ndev) { printk("%s: could not allocate device.\n", CARDNAME); return -ENOMEM; } SET_NETDEV_DEV(ndev, &pdev->dev); PRINTK2("dm9000_probe()");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -