dm9000c 移值新内核 linux-4.1.24

错误 1
/home/dm9000/dm9dev9000c.c:309: error: conflicting types for 'phy_read'
include/linux/phy.h:637: error: previous definition of 'phy_read' was here
/home/dm9000/dm9dev9000c.c:310: error: conflicting types for 'phy_write'
include/linux/phy.h:652: error: previous definition of 'phy_write' was here
linux/phy.h 也定义了这个函数,所以这里要改名.
phy_read 改名为 dm9000_phy_read
错误 2
dm9dev9000c.c:356: error: implicit declaration of function 'SET_MODULE_OWNER'
查看 linux2.6.22 源码查看发现只是一个宏定义 #define SET_MODULE_OWNER(dev) do { } while (0)
错误 3
/home/dm9000/dm9dev9000c.c:407: error: 'struct net_device' has no member named 'priv'
/home/dm9000/dm9dev9000c.c:408: error: 'struct net_device' has no member named 'priv'
/home/dm9000/dm9dev9000c.c:422: error: 'struct net_device' has no member named 'open'
/home/dm9000/dm9dev9000c.c:423: error: 'struct net_device' has no member named 'hard_start_xmit'
/* Allocated board information structure */
memset(dev->priv, 0, sizeof(struct board_info));
db = (board_info_t *)dev->priv;
改为 
db = netdev_priv(dev);
/* Allocated board information structure */
memset(db, 0, sizeof(struct board_info));
这里改的比较多,最后见补丁吧
static const struct net_device_ops dm9000_netdev_ops = {
	.ndo_open		= dm9000_open,
	.ndo_stop		= dm9000_stop,
	.ndo_start_xmit		= dm9000_start_xmit,
	.ndo_tx_timeout		= dm9000_timeout,
	.ndo_set_rx_mode	= dm9000_hash_table,
	.ndo_do_ioctl		= dm9000_ioctl,
	.ndo_change_mtu		= eth_change_mtu,
	.ndo_set_features	= dm9000_set_features,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address	= eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= dm9000_poll_controller,
#endif
};
需要复制 内核自带的 dm9000.h
 /*
   dm9ks.c: Version 2.08 2007/02/12 
         A Davicom DM9000/DM9010 ISA NIC fast Ethernet driver for Linux.
     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-2007 DAVICOM Semiconductor,Inc. All Rights Reserved.
 V2.00 Spenser - 01/10/2005
             - Modification for PXA270 MAINSTONE.
             - Modified dmfe_tx_done().
             - Add dmfe_timeout().
 V2.01    10/07/2005    -Modified dmfe_timer()
             -Dected network speed 10/100M
 V2.02    10/12/2005    -Use link change to chage db->Speed
             -dmfe_open() wait for Link OK
 V2.03    11/22/2005    -Power-off and Power-on PHY in dmfe_init_dm9000()
             -support IOL
 V2.04    12/13/2005    -delay 1.6s between power-on and power-off in
              dmfe_init_dm9000()
             -set LED mode 1 in dmfe_init_dm9000()
             -add data bus driving capability in dmfe_init_dm9000()
              (optional)
 10/3/2006    -Add DM8606 read/write function by MDC and MDIO
 V2.06    01/03/2007    -CONT_RX_PKT_CNT=0xFFFF
             -modify dmfe_tx_done function
             -check RX FIFO pointer
             -if using physical address, re-define I/O function
             -add db->cont_rx_pkt_cnt=0 at the front of dmfe_packet_receive()
 V2.08    02/12/2007    -module parameter macro
             2.4  MODULE_PARM
             2.6  module_param
             -remove #include <linux/config>
               -fix dmfe_interrupt for kernel 2.6.20
 V2.09 05/24/2007    -support ethtool and mii-tool
 05/30/2007    -fix the driver bug when ifconfig eth0 (-)promisc and (-)allmulti.
 06/05/2007    -fix dm9000b issue(ex. 10M TX idle=65mA, 10M harmonic)
             -add flow control function (option)
 10/01/2007  -Add #include <asm/uaccess.h>
             -Modyfy dmfe_do_ioctl for kernel 2.6.7
 11/23/2007    -Add TDBUG to check TX FIFO pointer shift
             - Remove check_rx_ready()
           - Add #define CHECKSUM to modify CHECKSUM function
 12/20/2007  -Modify TX timeout routine(+)check TCR&0x01 
 */
 //#define CHECKSUM
 //#define TDBUG        /* check TX FIFO pointer */
 //#define RDBUG   /* check RX FIFO pointer */
 //#define DM8606
 #define DRV_NAME    "dm9KS"
 #define DRV_VERSION    "2.09"
 #define DRV_RELDATE    "2007-11-22"
 #ifdef MODVERSIONS
 #include <linux/modversions.h>
 #endif
 //#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/version.h>
 #include <asm/dma.h>
 #include <linux/spinlock.h>
 #include <linux/crc32.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <asm/uaccess.h>
 #ifdef CONFIG_ARCH_MAINSTONE
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #endif
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include "dm9000.h"
 /* Board/System/Debug information/definition ---------------- */
 #define DM9KS_ID        0x90000A46
 #define DM9010_ID        0x90100A46
 /*-------register name-----------------------*/
 #define DM9KS_NCR        0x00    /* Network control Reg.*/
 #define DM9KS_NSR        0x01    /* Network Status Reg.*/
 #define DM9KS_TCR        0x02    /* TX control Reg.*/
 #define DM9KS_RXCR        0x05    /* RX control Reg.*/
 #define DM9KS_BPTR        0x08
 #define DM9KS_FCTR        0x09
 #define DM9KS_FCR            0x0a
 #define DM9KS_EPCR        0x0b
 #define DM9KS_EPAR        0x0c
 #define DM9KS_EPDRL        0x0d
 #define DM9KS_EPDRH        0x0e
 #define DM9KS_GPR            0x1f    /* General purpose register */
 #define DM9KS_CHIPR        0x2c
 #define DM9KS_TCR2        0x2d
 #define DM9KS_SMCR        0x2f     /* Special Mode Control Reg.*/
 #define DM9KS_ETXCSR    0x30    /* Early Transmit control/status Reg.*/
 #define    DM9KS_TCCR        0x31    /* Checksum cntrol Reg. */
 #define DM9KS_RCSR        0x32    /* Receive Checksum status Reg.*/
 #define DM9KS_BUSCR        0x38
 #define DM9KS_MRCMDX    0xf0
 #define DM9KS_MRCMD        0xf2
 #define DM9KS_MDRAL        0xf4
 #define DM9KS_MDRAH        0xf5
 #define DM9KS_MWCMD        0xf8
 #define DM9KS_MDWAL        0xfa
 #define DM9KS_MDWAH        0xfb
 #define DM9KS_TXPLL        0xfc
 #define DM9KS_TXPLH        0xfd
 #define DM9KS_ISR            0xfe
 #define DM9KS_IMR            0xff
 /*---------------------------------------------*/
 #define DM9KS_REG05        0x30    /* SKIP_CRC/SKIP_LONG */
 #define DM9KS_REGFF        0xA3    /* IMR */
 #define DM9KS_DISINTR    0x80
 #define DM9KS_PHY            0x40    /* PHY address 0x01 */
 #define DM9KS_PKT_RDY        0x01    /* Packet ready to receive */
 /* Added for PXA of MAINSTONE */
 #ifdef CONFIG_ARCH_MAINSTONE
 #include <asm/arch/mainstone.h>
 #define DM9KS_MIN_IO        (MST_ETH_PHYS + 0x300)
 #define DM9KS_MAX_IO            (MST_ETH_PHYS + 0x370)
 #define DM9K_IRQ        MAINSTONE_IRQ(3)
 #else
 #define DM9KS_MIN_IO        0x300
 #define DM9KS_MAX_IO        0x370
 #define DM9KS_IRQ        3
 #endif
 #define DM9KS_VID_L        0x28
 #define DM9KS_VID_H        0x29
 #define DM9KS_PID_L        0x2A
 #define DM9KS_PID_H        0x2B
 #define DM9KS_RX_INTR        0x01
 #define DM9KS_TX_INTR        0x02
 #define DM9KS_LINK_INTR        0x20
 #define DM9KS_DWORD_MODE    1
 #define DM9KS_BYTE_MODE        2
 #define DM9KS_WORD_MODE        0
 #define TRUE            1
 #define FALSE            0
 /* Number of continuous Rx packets */
 #define CONT_RX_PKT_CNT        0xFFFF
 #define DMFE_TIMER_WUT  jiffies+(HZ*5)    /* timer wakeup time : 5 second */
 #ifdef DM9KS_DEBUG
 #define DMFE_DBUG(dbug_now, msg, vaule)\
 if (dmfe_debug||dbug_now) printk(KERN_ERR "dmfe: %s %x\n", msg, vaule)
 #else
 #define DMFE_DBUG(dbug_now, msg, vaule)\
 if (dbug_now) printk(KERN_ERR "dmfe: %s %x\n", msg, vaule)
 #endif
 #ifndef CONFIG_ARCH_MAINSTONE
 #pragma pack(push, 1)
 #endif
 typedef struct _RX_DESC
 {
     u8 rxbyte;
     u8 status;
     u16 length;
 }RX_DESC;
 typedef union{
     u8 buf[];
     RX_DESC desc;
 } rx_t;
 #ifndef CONFIG_ARCH_MAINSTONE
 #pragma pack(pop)
 #endif
 enum DM9KS_PHY_mode {
     DM9KS_10MHD   = ,
     DM9KS_100MHD  = ,
     DM9KS_10MFD   = ,
     DM9KS_100MFD  = ,
     DM9KS_AUTO    = ,
 };
 /* Structure/enum declaration ------------------------------- */
 typedef struct board_info {
     u32 io_addr;/* Register I/O base address */
     u32 io_data;/* Data I/O address */
     u8 op_mode;/* PHY operation mode */
     u8 io_mode;/* 0:word, 2:byte */
     u8 Speed;    /* current speed */
     u8 chip_revision;
     int rx_csum;/* 0:disable, 1:enable */
     u32 reset_counter;/* counter: RESET */
     u32 reset_tx_timeout;/* RESET caused by TX Timeout */
     int tx_pkt_cnt;
     int cont_rx_pkt_cnt;/* current number of continuos rx packets  */
     struct net_device_stats stats;
     struct timer_list timer;
     unsigned char srom[];
     spinlock_t lock;
     struct mii_if_info mii;
 } board_info_t;
 /* Global variable declaration ----------------------------- */
 /*static int dmfe_debug = 0;*/
 static struct net_device * dmfe_dev = NULL;
 static struct ethtool_ops dmfe_ethtool_ops;
 /* For module input parameter */
 static int mode       = DM9KS_AUTO;
 static int media_mode = DM9KS_AUTO;
 static int  irq        = DM9KS_IRQ;
 static int iobase     = DM9KS_MIN_IO;
 #if 0  // use physical address; Not virtual address
 #ifdef outb
     #undef outb
 #endif
 #ifdef outw
     #undef outw
 #endif
 #ifdef outl
     #undef outl
 #endif
 #ifdef inb
     #undef inb
 #endif
 #ifdef inw
     #undef inw
 #endif
 #ifdef inl
     #undef inl
 #endif
 void outb(u8 reg, u32 ioaddr)
 {
     (*(volatile u8 *)(ioaddr)) = reg;
 }
 void outw(u16 reg, u32 ioaddr)
 {
     (*(volatile u16 *)(ioaddr)) = reg;
 }
 void outl(u32 reg, u32 ioaddr)
 {
     (*(volatile u32 *)(ioaddr)) = reg;
 }
 u8 inb(u32 ioaddr)
 {
     return (*(volatile u8 *)(ioaddr));
 }
 u16 inw(u32 ioaddr)
 {
     return (*(volatile u16 *)(ioaddr));
 }
 u32 inl(u32 ioaddr)
 {
     return (*(volatile u32 *)(ioaddr));
 }
 #endif
 /* function declaration ------------------------------------- */
 int dmfe_probe1(struct net_device *);
 static int dmfe_open(struct net_device *);
 static int dmfe_start_xmit(struct sk_buff *, struct net_device *);
 static void dmfe_tx_done(unsigned long);
 static void dmfe_packet_receive(struct net_device *);
 static int dmfe_stop(struct net_device *);
 static int dmfe_do_ioctl(struct net_device *, struct ifreq *, int);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 static void dmfe_interrupt(int , void *, struct pt_regs *);
 #else
     #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
     static irqreturn_t dmfe_interrupt(int , void *, struct pt_regs *);
     #else
     static irqreturn_t dmfe_interrupt(int , void *);/* for kernel 2.6.20 */
     #endif
 #endif
 static void dmfe_timer(unsigned long);
 static void dmfe_init_dm9000(struct net_device *);
 u8 ior(board_info_t *, int);
 void iow(board_info_t *, int, u8);
 static u16 dm9000_phy_read(board_info_t *, int);
 static void dm9000_phy_write(board_info_t *, int, u16);
 static u16 read_srom_word(board_info_t *, int);
 static void dm9000_hash_table(struct net_device *);
 static void dmfe_timeout(struct net_device *);
 static void dmfe_reset(struct net_device *);
 static int mdio_read(struct net_device *, int, int);
 static void mdio_write(struct net_device *, int, int, int);
 static void dmfe_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
 static int dmfe_get_settings(struct net_device *, struct ethtool_cmd *);
 static int dmfe_set_settings(struct net_device *, struct ethtool_cmd *);
 static u32 dmfe_get_link(struct net_device *);
 static int dmfe_nway_reset(struct net_device *);
 #ifdef DM8606
 #include "dm8606.h"
 #endif
 //DECLARE_TASKLET(dmfe_tx_tasklet,dmfe_tx_done,0);
 /* DM9000 network baord routine ---------------------------- */
 /*
   Search DM9000 board, allocate space and register it
 */
 struct net_device * __init dmfe_probe(void)
 {
     struct net_device *dev;
     int err;
     DMFE_DBUG(, "dmfe_probe()",);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
     dev = init_etherdev(NULL, sizeof(struct board_info));
     //ether_setup(dev);
 #else
     dev= alloc_etherdev(sizeof(struct board_info));
 #endif
     if(!dev)
         return ERR_PTR(-ENOMEM);
          //SET_MODULE_OWNER(dev);
     err = dmfe_probe1(dev);
     if (err)
         goto out;
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
     err = register_netdev(dev);
     if (err)
         goto out1;
 #endif
     return dev;
 out1:
     release_region(dev->base_addr,);
 out:
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
     kfree(dev);
 #else
     free_netdev(dev);
 #endif
     return ERR_PTR(err);
 }
 static int dm9000_set_features(struct net_device *dev,
     netdev_features_t features)
 {
     struct board_info *dm = netdev_priv(dev);
     netdev_features_t changed = dev->features ^ features;
     unsigned long flags;
     if (!(changed & NETIF_F_RXCSUM))
         return ;
     spin_lock_irqsave(&dm->lock, flags);
     iow(dm, DM9000_RCSR, (features & NETIF_F_RXCSUM) ? RCSR_CSUM : );
     spin_unlock_irqrestore(&dm->lock, flags);
     return ;
 }
 static const struct net_device_ops dm9000_netdev_ops = {
     .ndo_open        = dmfe_open,
     .ndo_stop        = dmfe_stop,
     .ndo_start_xmit        = dmfe_start_xmit,
     .ndo_tx_timeout        = dmfe_timeout,
     .ndo_do_ioctl        = dmfe_do_ioctl,
     .ndo_change_mtu        = eth_change_mtu,
     .ndo_set_mac_address= eth_mac_addr,
     .ndo_validate_addr    = eth_validate_addr,
     .ndo_set_features    = dm9000_set_features,
     .ndo_set_rx_mode    = dm9000_hash_table,
 #ifdef CONFIG_NET_POLL_CONTROLLER
     .ndo_poll_controller    = dm9000_poll_controller,
 #endif
 };
 int __init dmfe_probe1(struct net_device *dev)
 {
     struct board_info *db;    /* Point a board information structure */
     u32 id_val;
     u16 i, dm9000_found = FALSE;
     u8 MAC_addr[]={0x00,0x60,0x6E,0x33,0x44,0x55};
     u8 HasEEPROM=,chip_info;
     DMFE_DBUG(, "dmfe_probe1()",);
     /* Search All DM9000 serial NIC */
     do {
         outb(DM9KS_VID_L, iobase); /* DM9000C的索引寄存器(cmd引脚为0) */
         id_val = inb(iobase + );  /* 读DM9000C的数据寄存器(cmd引脚为1) */
         outb(DM9KS_VID_H, iobase);
         id_val |= inb(iobase + ) << ;
         outb(DM9KS_PID_L, iobase);
         id_val |= inb(iobase + ) << ;
         outb(DM9KS_PID_H, iobase);
         id_val |= inb(iobase + ) << ;
         if (id_val == DM9KS_ID || id_val == DM9010_ID) {
             /* Request IO from system */
             if(!request_region(iobase, , dev->name))
                 return -ENODEV;
             printk(KERN_ERR"<DM9KS> I/O: %x, VID: %x \n",iobase, id_val);
             dm9000_found = TRUE;
             db = netdev_priv(dev);
             /* Allocated board information structure */
             memset(db, , sizeof(struct board_info));
             dmfe_dev    = dev;
             db->io_addr  = iobase;
             db->io_data = iobase + ;
             db->chip_revision = ior(db, DM9KS_CHIPR);
             chip_info = ior(db,0x43);
             /* thisway.diy@163.com */
             //if((db->chip_revision!=0x1A) || ((chip_info&(1<<5))!=0) || ((chip_info&(1<<2))!=1)) return -ENODEV;
             /* driver system function */
             dev->netdev_ops    = &dm9000_netdev_ops;
             dev->base_addr         = iobase;
             dev->irq         = irq;
             //dev->open         = &dmfe_open;
             //dev->hard_start_xmit     = &dmfe_start_xmit;
             dev->watchdog_timeo    = *HZ;
             //dev->tx_timeout        = dmfe_timeout;
             //dev->stop         = &dmfe_stop;
             //dev->get_stats         = &dmfe_get_stats;
             //dev->set_multicast_list = &dm9000_hash_table;
             //dev->do_ioctl         = &dmfe_do_ioctl;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,28)
             dev->ethtool_ops = &dmfe_ethtool_ops;
 #endif
 #ifdef CHECKSUM
             //dev->features |=  NETIF_F_IP_CSUM;
             dev->features |=  NETIF_F_IP_CSUM|NETIF_F_SG;
 #endif
             db->mii.dev = dev;
             db->mii.mdio_read = mdio_read;
             db->mii.mdio_write = mdio_write;
             db->mii.phy_id = ;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)
             db->mii.phy_id_mask = 0x1F;
             db->mii.reg_num_mask = 0x1F;
 #endif
             //db->msg_enable =(debug == 0 ? DMFE_DEF_MSG_ENABLE : ((1 << debug) - 1));
             /* Read SROM content */
             for (i=; i<; i++)
                 ((u16 *)db->srom)[i] = read_srom_word(db, i);
             /* Get the PID and VID from EEPROM to check */
             id_val = (((u16 *)db->srom)[])|(((u16 *)db->srom)[]<<);
             printk("id_val=%x\n", id_val);
             if (id_val == DM9KS_ID || id_val == DM9010_ID)
                 HasEEPROM =;
             /* Set Node Address */
             for (i=; i<; i++)
             {
                 if (HasEEPROM) /* use EEPROM */
                     dev->dev_addr[i] = db->srom[i];
                 else    /* No EEPROM */
                     dev->dev_addr[i] = MAC_addr[i];
             }
         }//end of if()
         iobase += 0x10;
     }while(!dm9000_found && iobase <= DM9KS_MAX_IO);
     return dm9000_found ? :-ENODEV;
 }
 /*
   Open the interface.
   The interface is opened whenever "ifconfig" actives it.
 */
 static int dmfe_open(struct net_device *dev)
 {
     board_info_t *db = netdev_priv(dev);
     u8 reg_nsr;
     int i;
     DMFE_DBUG(, "dmfe_open", );
     /* thisway.diy@163.com */
     if (request_irq(dev->irq,&dmfe_interrupt, IRQF_TRIGGER_RISING,dev->name,dev))
         return -EAGAIN;
     /* Initilize DM910X board */
     dmfe_init_dm9000(dev);
 #ifdef DM8606
     // control DM8606
     printk("[8606]reg0=0x%04x\n",dm8606_read(db,));
     printk("[8606]reg1=0x%04x\n",dm8606_read(db,0x1));
 #endif
     /* Init driver variable */
     db->reset_counter     = ;
     db->reset_tx_timeout     = ;
     db->cont_rx_pkt_cnt    = ;
     /* check link state and media speed */
     db->Speed =;
     i=;
     do {
         reg_nsr = ior(db,DM9KS_NSR);
         if(reg_nsr & 0x40) /* link OK!! */
         {
             /* wait for detected Speed */
             mdelay();
             reg_nsr = ior(db,DM9KS_NSR);
             if(reg_nsr & 0x80)
                 db->Speed =;
             else
                 db->Speed =;
             break;
         }
         i++;
         mdelay();
     }while(i<);    /* wait 3 second  */
     //printk("i=%d  Speed=%d\n",i,db->Speed);
     /* set and active a timer process */
     init_timer(&db->timer);
     db->timer.expires     = DMFE_TIMER_WUT;
     db->timer.data         = (unsigned long)dev;
     db->timer.function     = &dmfe_timer;
     add_timer(&db->timer);    //Move to DM9000 initiallization was finished.
     netif_start_queue(dev);
     return ;
 }
 /* Set PHY operationg mode
 */
 static void set_PHY_mode(board_info_t *db)
 {
 #ifndef DM8606
     u16 phy_reg0 = 0x1000;/* Auto-negotiation*/
     u16 phy_reg4 = 0x01e1;
     if ( !(db->op_mode & DM9KS_AUTO) ) // op_mode didn't auto sense */
     {
         switch(db->op_mode) {
             case DM9KS_10MHD:  phy_reg4 = 0x21;
                                        phy_reg0 = 0x1000;
                        break;
             case DM9KS_10MFD:  phy_reg4 = 0x41;
                        phy_reg0 = 0x1100;
                                        break;
             case DM9KS_100MHD: phy_reg4 = 0x81;
                        phy_reg0 = 0x3000;
                            break;
             case DM9KS_100MFD: phy_reg4 = 0x101;
                        phy_reg0 = 0x3100;
                           break;
             default:
                        break;
         } // end of switch
     } // end of if
 #ifdef FLOW_CONTROL
     dm9000_phy_write(db, , phy_reg4|(<<));
 #else
     dm9000_phy_write(db, , phy_reg4);
 #endif //end of FLOW_CONTROL
     dm9000_phy_write(db, , phy_reg0|0x200);
 #else
     /* Fiber mode */
     dm9000_phy_write(db, , 0x4014);
     dm9000_phy_write(db, , 0x2100);
 #endif //end of DM8606
     if (db->chip_revision == 0x1A)
     {
         //set 10M TX idle =65mA (TX 100% utility is 160mA)
         dm9000_phy_write(db,, dm9000_phy_read(db,)|(<<)|(<<));
         //:fix harmonic
         //For short code:
         //PHY_REG 27 (1Bh) <- 0000h
         dm9000_phy_write(db, , 0x0000);
         //PHY_REG 27 (1Bh) <- AA00h
         dm9000_phy_write(db, , 0xaa00);
         //PHY_REG 27 (1Bh) <- 0017h
         dm9000_phy_write(db, , 0x0017);
         //PHY_REG 27 (1Bh) <- AA17h
         dm9000_phy_write(db, , 0xaa17);
         //PHY_REG 27 (1Bh) <- 002Fh
         dm9000_phy_write(db, , 0x002f);
         //PHY_REG 27 (1Bh) <- AA2Fh
         dm9000_phy_write(db, , 0xaa2f);
         //PHY_REG 27 (1Bh) <- 0037h
         dm9000_phy_write(db, , 0x0037);
         //PHY_REG 27 (1Bh) <- AA37h
         dm9000_phy_write(db, , 0xaa37);
         //PHY_REG 27 (1Bh) <- 0040h
         dm9000_phy_write(db, , 0x0040);
         //PHY_REG 27 (1Bh) <- AA40h
         dm9000_phy_write(db, , 0xaa40);
         //For long code:
         //PHY_REG 27 (1Bh) <- 0050h
         dm9000_phy_write(db, , 0x0050);
         //PHY_REG 27 (1Bh) <- AA50h
         dm9000_phy_write(db, , 0xaa50);
         //PHY_REG 27 (1Bh) <- 006Bh
         dm9000_phy_write(db, , 0x006b);
         //PHY_REG 27 (1Bh) <- AA6Bh
         dm9000_phy_write(db, , 0xaa6b);
         //PHY_REG 27 (1Bh) <- 007Dh
         dm9000_phy_write(db, , 0x007d);
         //PHY_REG 27 (1Bh) <- AA7Dh
         dm9000_phy_write(db, , 0xaa7d);
         //PHY_REG 27 (1Bh) <- 008Dh
         dm9000_phy_write(db, , 0x008d);
         //PHY_REG 27 (1Bh) <- AA8Dh
         dm9000_phy_write(db, , 0xaa8d);
         //PHY_REG 27 (1Bh) <- 009Ch
         dm9000_phy_write(db, , 0x009c);
         //PHY_REG 27 (1Bh) <- AA9Ch
         dm9000_phy_write(db, , 0xaa9c);
         //PHY_REG 27 (1Bh) <- 00A3h
         dm9000_phy_write(db, , 0x00a3);
         //PHY_REG 27 (1Bh) <- AAA3h
         dm9000_phy_write(db, , 0xaaa3);
         //PHY_REG 27 (1Bh) <- 00B1h
         dm9000_phy_write(db, , 0x00b1);
         //PHY_REG 27 (1Bh) <- AAB1h
         dm9000_phy_write(db, , 0xaab1);
         //PHY_REG 27 (1Bh) <- 00C0h
         dm9000_phy_write(db, , 0x00c0);
         //PHY_REG 27 (1Bh) <- AAC0h
         dm9000_phy_write(db, , 0xaac0);
         //PHY_REG 27 (1Bh) <- 00D2h
         dm9000_phy_write(db, , 0x00d2);
         //PHY_REG 27 (1Bh) <- AAD2h
         dm9000_phy_write(db, , 0xaad2);
         //PHY_REG 27 (1Bh) <- 00E0h
         dm9000_phy_write(db, , 0x00e0);
         //PHY_REG 27 (1Bh) <- AAE0h
         dm9000_phy_write(db, , 0xaae0);
         //PHY_REG 27 (1Bh) <- 0000h
         dm9000_phy_write(db, , 0x0000);
     }
 }
 /*
     Initilize dm9000 board
 */
 static void dmfe_init_dm9000(struct net_device *dev)
 {
     board_info_t *db = netdev_priv(dev);
     DMFE_DBUG(, "dmfe_init_dm9000()", );
     spin_lock_init(&db->lock);
     iow(db, DM9KS_GPR, );    /* GPR (reg_1Fh)bit GPIO0=0 pre-activate PHY */
     mdelay();        /* wait for PHY power-on ready */
     /* do a software reset and wait 20us */
     iow(db, DM9KS_NCR, );
     udelay();        /* wait 20us at least for software reset ok */
     iow(db, DM9KS_NCR, );    /* NCR (reg_00h) bit[0] RST=1 & Loopback=1, reset on */
     udelay();        /* wait 20us at least for software reset ok */
     /* I/O mode */
     db->io_mode = ior(db, DM9KS_ISR) >> ; /* ISR bit7:6 keeps I/O mode */
     /* Set PHY */
     db->op_mode = media_mode;
     set_PHY_mode(db);
     /* Program operating register */
     iow(db, DM9KS_NCR, );
     iow(db, DM9KS_TCR, );        /* TX Polling clear */
     iow(db, DM9KS_BPTR, 0x3f);    /* Less 3kb, 600us */
     iow(db, DM9KS_SMCR, );        /* Special Mode */
     iow(db, DM9KS_NSR, 0x2c);    /* clear TX status */
     iow(db, DM9KS_ISR, 0x0f);     /* Clear interrupt status */
     iow(db, DM9KS_TCR2, 0x80);    /* Set LED mode 1 */
     if (db->chip_revision == 0x1A){
         /* Data bus current driving/sinking capability  */
         iow(db, DM9KS_BUSCR, 0x01);    /* default: 2mA */
     }
 #ifdef FLOW_CONTROL
     iow(db, DM9KS_BPTR, 0x37);
     iow(db, DM9KS_FCTR, 0x38);
     iow(db, DM9KS_FCR, 0x29);
 #endif
 #ifdef DM8606
     iow(db,0x34,);
 #endif
     if (dev->features & NETIF_F_HW_CSUM){
         printk(KERN_INFO "DM9KS:enable TX checksum\n");
         iow(db, DM9KS_TCCR, 0x07);    /* TX UDP/TCP/IP checksum enable */
     }
     if (db->rx_csum){
         printk(KERN_INFO "DM9KS:enable RX checksum\n");
         iow(db, DM9KS_RCSR, 0x02);    /* RX checksum enable */
     }
 #ifdef ETRANS
     /*If TX loading is heavy, the driver can try to anbel "early transmit".
     The programmer can tune the "Early Transmit Threshold" to get
     the optimization. (DM9KS_ETXCSR.[1-0])
     Side Effect: It will happen "Transmit under-run". When TX under-run
     always happens, the programmer can increase the value of "Early
     Transmit Threshold". */
     iow(db, DM9KS_ETXCSR, 0x83);
 #endif
     /* Set address filter table */
     dm9000_hash_table(dev);
     /* Activate DM9000/DM9010 */
     iow(db, DM9KS_IMR, DM9KS_REGFF); /* Enable TX/RX interrupt mask */
     iow(db, DM9KS_RXCR, DM9KS_REG05 | );    /* RX enable */
     /* Init Driver variable */
     db->tx_pkt_cnt         = ;
     netif_carrier_on(dev);
 }
 /*
   Hardware start transmission.
   Send a packet to media from the upper layer.
 */
 static int dmfe_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
     board_info_t *db = netdev_priv(dev);
     char * data_ptr;
     int i, tmplen;
     u16 MDWAH, MDWAL;
     #ifdef TDBUG /* check TX FIFO pointer */
             u16 MDWAH1, MDWAL1;
             u16 tx_ptr;
     #endif
     DMFE_DBUG(, "dmfe_start_xmit", );
     if (db->chip_revision != 0x1A)
     {
         if(db->Speed == )
             {if (db->tx_pkt_cnt >= ) return ;}
         else
             {if (db->tx_pkt_cnt >= ) return ;}
     }else
         if (db->tx_pkt_cnt >= ) return ;
     /* packet counting */
     db->tx_pkt_cnt++;
     db->stats.tx_packets++;
     db->stats.tx_bytes+=skb->len;
     if (db->chip_revision != 0x1A)
     {
         if (db->Speed == )
             {if (db->tx_pkt_cnt >= ) netif_stop_queue(dev);}
         else
             {if (db->tx_pkt_cnt >= ) netif_stop_queue(dev);}
     }else
         if (db->tx_pkt_cnt >= ) netif_stop_queue(dev);        
     /* Disable all interrupt */
     iow(db, DM9KS_IMR, DM9KS_DISINTR);
     MDWAH = ior(db,DM9KS_MDWAH);
     MDWAL = ior(db,DM9KS_MDWAL);
     /* Set TX length to reg. 0xfc & 0xfd */
     iow(db, DM9KS_TXPLL, (skb->len & 0xff));
     iow(db, DM9KS_TXPLH, (skb->len >> ) & 0xff);
     /* Move data to TX SRAM */
     data_ptr = (char *)skb->data;
     outb(DM9KS_MWCMD, db->io_addr); // Write data into SRAM trigger
     switch(db->io_mode)
     {
         case DM9KS_BYTE_MODE:
             for (i = ; i < skb->len; i++)
                 outb((data_ptr[i] & 0xff), db->io_data);
             break;
         case DM9KS_WORD_MODE:
             tmplen = (skb->len + ) / ;
             for (i = ; i < tmplen; i++)
         outw(((u16 *)data_ptr)[i], db->io_data);
       break;
     case DM9KS_DWORD_MODE:
       tmplen = (skb->len + ) / ;
             for (i = ; i< tmplen; i++)
                 outl(((u32 *)data_ptr)[i], db->io_data);
             break;
     }
 #ifndef ETRANS
     /* Issue TX polling command */
     iow(db, DM9KS_TCR, 0x1); /* Cleared after TX complete*/
 #endif
     #ifdef TDBUG /* check TX FIFO pointer */
             MDWAH1 = ior(db,DM9KS_MDWAH);
             MDWAL1 = ior(db,DM9KS_MDWAL);
             tx_ptr = (MDWAH<<)|MDWAL;
             switch (db->io_mode)
             {
                 case DM9KS_BYTE_MODE:
                     tx_ptr += skb->len;
                     break;
                 case DM9KS_WORD_MODE:
                     tx_ptr += ((skb->len + ) / )*;
                     break;
                 case DM9KS_DWORD_MODE:
                     tx_ptr += ((skb->len+)/)*;
                     break;
             }
             if (tx_ptr > 0x0bff)
                     tx_ptr -= 0x0c00;
             if (tx_ptr != ((MDWAH1<<)|MDWAL1))
                     printk("[dm9ks:TX FIFO ERROR\n");
     #endif
     /* Saved the time stamp */
     dev->trans_start = jiffies;
     db->cont_rx_pkt_cnt =;
     /* Free this SKB */
     dev_kfree_skb(skb);
     /* Re-enable interrupt */
     iow(db, DM9KS_IMR, DM9KS_REGFF);
     return ;
 }
 /*
   Stop the interface.
   The interface is stopped when it is brought.
 */
 static int dmfe_stop(struct net_device *dev)
 {
     board_info_t *db = netdev_priv(dev);
     DMFE_DBUG(, "dmfe_stop", );
     /* deleted timer */
     del_timer(&db->timer);
     netif_stop_queue(dev); 
     /* free interrupt */
     free_irq(dev->irq, dev);
     /* RESET devie */
     dm9000_phy_write(db, 0x00, 0x8000);    /* PHY RESET */
     //iow(db, DM9KS_GPR, 0x01);     /* Power-Down PHY */
     iow(db, DM9KS_IMR, DM9KS_DISINTR);    /* Disable all interrupt */
     iow(db, DM9KS_RXCR, 0x00);    /* Disable RX */
     /* Dump Statistic counter */
 #if FALSE
     printk("\nRX FIFO OVERFLOW %lx\n", db->stats.rx_fifo_errors);
     printk("RX CRC %lx\n", db->stats.rx_crc_errors);
     printk("RX LEN Err %lx\n", db->stats.rx_length_errors);
     printk("RESET %x\n", db->reset_counter);
     printk("RESET: TX Timeout %x\n", db->reset_tx_timeout);
     printk("g_TX_nsr %x\n", g_TX_nsr);
 #endif
     return ;
 }
 static void dmfe_tx_done(unsigned long unused)
 {
     struct net_device *dev = dmfe_dev;
     board_info_t *db = netdev_priv(dev);
     int  nsr;
     DMFE_DBUG(, "dmfe_tx_done()", );
     nsr = ior(db, DM9KS_NSR);
     if (nsr & 0x0c)
     {
         if(nsr & 0x04) db->tx_pkt_cnt--;
         if(nsr & 0x08) db->tx_pkt_cnt--;
         if(db->tx_pkt_cnt < )
         {
             printk(KERN_DEBUG "DM9KS:tx_pkt_cnt ERROR!!\n");
             while(ior(db,DM9KS_TCR) & 0x1){}
             db->tx_pkt_cnt = ;
         }
     }else{
         while(ior(db,DM9KS_TCR) & 0x1){}
         db->tx_pkt_cnt = ;
     }
     netif_wake_queue(dev);
     return;
 }
 /*
   DM9000 insterrupt handler
   receive the packet to upper layer, free the transmitted packet
 */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 #else
     #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
     static irqreturn_t dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     #else
     static irqreturn_t dmfe_interrupt(int irq, void *dev_id) /* for kernel 2.6.20*/
     #endif
 #endif
 {
     struct net_device *dev = dev_id;
     board_info_t *db;
     int int_status,i;
     u8 reg_save;
     DMFE_DBUG(, "dmfe_interrupt()", );
     /* A real interrupt coming */
     db = netdev_priv(dev);
     spin_lock(&db->lock);
     /* Save previous register address */
     reg_save = inb(db->io_addr);
     /* Disable all interrupt */
     iow(db, DM9KS_IMR, DM9KS_DISINTR); 
     /* Got DM9000/DM9010 interrupt status */
     int_status = ior(db, DM9KS_ISR);        /* Got ISR */
     iow(db, DM9KS_ISR, int_status);        /* Clear ISR status */ 
     /* Link status change */
     if (int_status & DM9KS_LINK_INTR)
     {
         netif_stop_queue(dev);
         for(i=; i<; i++) /*wait link OK, waiting time =0.5s */
         {
             dm9000_phy_read(db,0x1);
             if(dm9000_phy_read(db,0x1) & 0x4) /*Link OK*/
             {
                 /* wait for detected Speed */
                 for(i=; i<;i++)
                     udelay();
                 /* set media speed */
                 if(dm9000_phy_read(db,)&0x2000) db->Speed =;
                 else db->Speed =;
                 break;
             }
             udelay();
         }
         netif_wake_queue(dev);
         //printk("[INTR]i=%d speed=%d\n",i, (int)(db->Speed));
     }
     /* Received the coming packet */
     if (int_status & DM9KS_RX_INTR)
         dmfe_packet_receive(dev);
     /* Trnasmit Interrupt check */
     if (int_status & DM9KS_TX_INTR)
         dmfe_tx_done();
     if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT)
     {
         iow(db, DM9KS_IMR, 0xa2);
     }
     else
     {
         /* Re-enable interrupt mask */
         iow(db, DM9KS_IMR, DM9KS_REGFF);
     }
     /* Restore previous register address */
     outb(reg_save, db->io_addr); 
     spin_unlock(&db->lock);
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
     return IRQ_HANDLED;
 #endif
 }
 /*
  *    Process the ethtool ioctl command
  */
 static int dmfe_ethtool_ioctl(struct net_device *dev, void *useraddr)
 {
     //struct dmfe_board_info *db = dev->priv;
     struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
     u32 ethcmd;
     if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd)))
         return -EFAULT;
     switch (ethcmd)
     {
         case ETHTOOL_GDRVINFO:
             strcpy(info.driver, DRV_NAME);
             strcpy(info.version, DRV_VERSION);
             sprintf(info.bus_info, "ISA 0x%lx %d",dev->base_addr, dev->irq);
             if (copy_to_user(useraddr, &info, sizeof(info)))
                 return -EFAULT;
             return ;
     }
     return -EOPNOTSUPP;
 }
 /*
   Process the upper socket ioctl command
 */
 static int dmfe_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
     board_info_t *db = netdev_priv(dev);
     #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) /* for kernel 2.6.7 */
     struct mii_ioctl_data *data=(struct mii_ioctl_data *)&ifr->ifr_data;
     #endif
   int rc=;
     DMFE_DBUG(, "dmfe_do_ioctl()", );
         if (!netif_running(dev))
             return -EINVAL;
         if (cmd == SIOCETHTOOL)
         rc = dmfe_ethtool_ioctl(dev, (void *) ifr->ifr_data);
     else {
         spin_lock_irq(&db->lock);
         #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) /* for kernel 2.6.7 */
             rc = generic_mii_ioctl(&db->mii, data, cmd, NULL);
         #else
             rc = generic_mii_ioctl(&db->mii, if_mii(ifr), cmd, NULL);
         #endif
         spin_unlock_irq(&db->lock);
     }
     return rc;
 }
 /* Our watchdog timed out. Called by the networking layer */
 static void dmfe_timeout(struct net_device *dev)
 {
     board_info_t *db = netdev_priv(dev);
     int i;
     DMFE_DBUG(, "dmfe_TX_timeout()", );
     printk("TX time-out -- dmfe_timeout().\n");
     db->reset_tx_timeout++;
     db->stats.tx_errors++;
 #if FALSE
     printk("TX packet count = %d\n", db->tx_pkt_cnt);
     printk("TX timeout = %d\n", db->reset_tx_timeout);
     printk("22H=0x%02x  23H=0x%02x\n",ior(db,0x22),ior(db,0x23));
     printk("faH=0x%02x  fbH=0x%02x\n",ior(db,0xfa),ior(db,0xfb));
 #endif
     i=;
     while((i++<)&&(ior(db,DM9KS_TCR) & 0x01))
     {
         udelay();
     }
     if(i<)
     {
             db->tx_pkt_cnt = ;
             netif_wake_queue(dev);
     }
     else
     {
             dmfe_reset(dev);
     }
 }
 static void dmfe_reset(struct net_device * dev)
 {
     board_info_t *db = netdev_priv(dev);
     u8 reg_save;
     int i;
     /* Save previous register address */
     reg_save = inb(db->io_addr);
     netif_stop_queue(dev);
     db->reset_counter++;
     dmfe_init_dm9000(dev);
     db->Speed =;
     for(i=; i<; i++) /*wait link OK, waiting time=1 second */
     {
         if(dm9000_phy_read(db,0x1) & 0x4) /*Link OK*/
         {
             if(dm9000_phy_read(db,)&0x2000) db->Speed =;
             else db->Speed =;
             break;
         }
         udelay();
     }
     netif_wake_queue(dev);
     /* Restore previous register address */
     outb(reg_save, db->io_addr);
 }
 /*
   A periodic timer routine
 */
 static void dmfe_timer(unsigned long data)
 {
     struct net_device * dev = (struct net_device *)data;
     board_info_t *db = netdev_priv(dev);
     DMFE_DBUG(, "dmfe_timer()", );
     if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT)
     {
         db->cont_rx_pkt_cnt=;
         iow(db, DM9KS_IMR, DM9KS_REGFF);
     }
     /* Set timer again */
     db->timer.expires = DMFE_TIMER_WUT;
     add_timer(&db->timer);
     return;
 }
 /*
   Received a packet and pass to upper layer
 */
 static void dmfe_packet_receive(struct net_device *dev)
 {
     board_info_t *db = netdev_priv(dev);
     struct sk_buff *skb;
     u8 rxbyte;
     u16 i, GoodPacket, tmplen = , MDRAH, MDRAL;
     u32 tmpdata;
     rx_t rx;
     u16 * ptr = (u16*)℞
     u8* rdptr;
     DMFE_DBUG(, "dmfe_packet_receive()", );
     db->cont_rx_pkt_cnt=;
     do {
         /*store the value of Memory Data Read address register*/
         MDRAH=ior(db, DM9KS_MDRAH);
         MDRAL=ior(db, DM9KS_MDRAL);
         ior(db, DM9KS_MRCMDX);        /* Dummy read */
         rxbyte = inb(db->io_data);    /* Got most updated data */
 #ifdef CHECKSUM
         if (rxbyte&0x2)            /* check RX byte */
         {
       printk("dm9ks: abnormal!\n");
             dmfe_reset(dev);
             break;
     }else {
       if (!(rxbyte&0x1))
                 break;
     }
 #else
         if (rxbyte==)
             break;
         if (rxbyte>)
         {
       printk("dm9ks: Rxbyte error!\n");
           dmfe_reset(dev);
       break;
     }
 #endif
         /* A packet ready now  & Get status/length */
         GoodPacket = TRUE;
         outb(DM9KS_MRCMD, db->io_addr);
         /* Read packet status & length */
         switch (db->io_mode)
             {
               case DM9KS_BYTE_MODE:
                      *ptr = inb(db->io_data) +
                                (inb(db->io_data) << );
                     *(ptr+) = inb(db->io_data) +
                         (inb(db->io_data) << );
                     break;
               case DM9KS_WORD_MODE:
                     *ptr = inw(db->io_data);
                     *(ptr+)    = inw(db->io_data);
                     break;
               case DM9KS_DWORD_MODE:
                     tmpdata  = inl(db->io_data);
                     *ptr = tmpdata;
                     *(ptr+)    = tmpdata >> ;
                     break;
               default:
                     break;
             }
         /* Packet status check */
         if (rx.desc.status & 0xbf)
         {
             GoodPacket = FALSE;
             if (rx.desc.status & 0x01)
             {
                 db->stats.rx_fifo_errors++;
                 printk(KERN_INFO"<RX FIFO error>\n");
             }
             if (rx.desc.status & 0x02)
             {
                 db->stats.rx_crc_errors++;
                 printk(KERN_INFO"<RX CRC error>\n");
             }
             if (rx.desc.status & 0x80)
             {
                 db->stats.rx_length_errors++;
                 printk(KERN_INFO"<RX Length error>\n");
             }
             if (rx.desc.status & 0x08)
                 printk(KERN_INFO"<Physical Layer error>\n");
         }
         if (!GoodPacket)
         {
             // drop this packet!!!
             switch (db->io_mode)
             {
                 case DM9KS_BYTE_MODE:
                      for (i=; i<rx.desc.length; i++)
                         inb(db->io_data);
                     break;
                 case DM9KS_WORD_MODE:
                     tmplen = (rx.desc.length + ) / ;
                     for (i = ; i < tmplen; i++)
                         inw(db->io_data);
                     break;
                 case DM9KS_DWORD_MODE:
                     tmplen = (rx.desc.length + ) / ;
                     for (i = ; i < tmplen; i++)
                         inl(db->io_data);
                     break;
             }
             continue;/*next the packet*/
         }
         skb = dev_alloc_skb(rx.desc.length+);
         if (skb == NULL )
         {
             printk(KERN_INFO "%s: Memory squeeze.\n", dev->name);
             /*re-load the value into Memory data read address register*/
             iow(db,DM9KS_MDRAH,MDRAH);
             iow(db,DM9KS_MDRAL,MDRAL);
             return;
         }
         else
         {
             /* Move data from DM9000 */
             skb->dev = dev;
             skb_reserve(skb, );
             rdptr = (u8*)skb_put(skb, rx.desc.length - );
             /* Read received packet from RX SARM */
             switch (db->io_mode)
             {
                 case DM9KS_BYTE_MODE:
                      for (i=; i<rx.desc.length; i++)
                         rdptr[i]=inb(db->io_data);
                     break;
                 case DM9KS_WORD_MODE:
                     tmplen = (rx.desc.length + ) / ;
                     for (i = ; i < tmplen; i++)
                         ((u16 *)rdptr)[i] = inw(db->io_data);
                     break;
                 case DM9KS_DWORD_MODE:
                     tmplen = (rx.desc.length + ) / ;
                     for (i = ; i < tmplen; i++)
                         ((u32 *)rdptr)[i] = inl(db->io_data);
                     break;
             }
             /* Pass to upper layer */
             skb->protocol = eth_type_trans(skb,dev);
 #ifdef CHECKSUM
         if((rxbyte&0xe0)==)    /* receive packet no checksum fail */
                 skb->ip_summed = CHECKSUM_UNNECESSARY;
 #endif
             netif_rx(skb);
             dev->last_rx=jiffies;
             db->stats.rx_packets++;
             db->stats.rx_bytes += rx.desc.length;
             db->cont_rx_pkt_cnt++;
 #ifdef RDBG /* check RX FIFO pointer */
             u16 MDRAH1, MDRAL1;
             u16 tmp_ptr;
             MDRAH1 = ior(db,DM9KS_MDRAH);
             MDRAL1 = ior(db,DM9KS_MDRAL);
             tmp_ptr = (MDRAH<<)|MDRAL;
             switch (db->io_mode)
             {
                 case DM9KS_BYTE_MODE:
                     tmp_ptr += rx.desc.length+;
                     break;
                 case DM9KS_WORD_MODE:
                     tmp_ptr += ((rx.desc.length+)/)*+;
                     break;
                 case DM9KS_DWORD_MODE:
                     tmp_ptr += ((rx.desc.length+)/)*+;
                     break;
             }
             if (tmp_ptr >=0x4000)
                 tmp_ptr = (tmp_ptr - 0x4000) + 0xc00;
             if (tmp_ptr != ((MDRAH1<<)|MDRAL1))
                 printk("[dm9ks:RX FIFO ERROR\n");
 #endif
             if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT)
             {
                 dmfe_tx_done();
                 break;
             }
         }
     }while((rxbyte & 0x01) == DM9KS_PKT_RDY);
     DMFE_DBUG(, "[END]dmfe_packet_receive()", );
 }
 /*
   Read a word data from SROM
 */
 static u16 read_srom_word(board_info_t *db, int offset)
 {
     iow(db, DM9KS_EPAR, offset);
     iow(db, DM9KS_EPCR, 0x4);
     while(ior(db, DM9KS_EPCR)&0x1);    /* Wait read complete */
     iow(db, DM9KS_EPCR, 0x0);
     return (ior(db, DM9KS_EPDRL) + (ior(db, DM9KS_EPDRH) << ) );
 }
 /*
  *  Set DM9000 multicast address
  */
 static void dm9000_hash_table_unlocked(struct net_device *dev)
 {
     struct board_info *db = netdev_priv(dev);
     struct netdev_hw_addr *ha;
     int i, oft;
     u32 hash_val;
     u16 hash_table[] = { , , , 0x8000 }; /* broadcast address */
     u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;
     //dm9000_dbg(db, 1, "entering %s\n", __func__);
     for (i = , oft = DM9000_PAR; i < ; i++, oft++)
         iow(db, oft, dev->dev_addr[i]);
     if (dev->flags & IFF_PROMISC)
         rcr |= RCR_PRMSC;
     if (dev->flags & IFF_ALLMULTI)
         rcr |= RCR_ALL;
     /* the multicast address in Hash Table : 64 bits */
     netdev_for_each_mc_addr(ha, dev) {
         hash_val = ether_crc_le(, ha->addr) & 0x3f;
         hash_table[hash_val / ] |= (u16)  << (hash_val % );
     }
     /* Write the hash table to MAC MD table */
     for (i = , oft = DM9000_MAR; i < ; i++) {
         iow(db, oft++, hash_table[i]);
         iow(db, oft++, hash_table[i] >> );
     }
     iow(db, DM9000_RCR, rcr);
 }
 static void dm9000_hash_table(struct net_device *dev)
 {
     struct board_info *db = netdev_priv(dev);
     unsigned long flags;
     spin_lock_irqsave(&db->lock, flags);
     dm9000_hash_table_unlocked(dev);
     spin_unlock_irqrestore(&db->lock, flags);
 }
 static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
     board_info_t *db = netdev_priv(dev);
     return dm9000_phy_read(db, location);
 }
 static void mdio_write(struct net_device *dev, int phy_id, int location, int val)
 {
     board_info_t *db = netdev_priv(dev);
     dm9000_phy_write(db, location, val);
 }
 /*
    Read a byte from I/O port
 */
 u8 ior(board_info_t *db, int reg)
 {
     outb(reg, db->io_addr);
     return inb(db->io_data);
 }
 /*
    Write a byte to I/O port
 */
 void iow(board_info_t *db, int reg, u8 value)
 {
     outb(reg, db->io_addr);
     outb(value, db->io_data);
 }
 /*
    Read a word from phyxcer
 */
 static u16 dm9000_phy_read(board_info_t *db, int reg)
 {
     /* Fill the phyxcer register into REG_0C */
     iow(db, DM9KS_EPAR, DM9KS_PHY | reg);
     iow(db, DM9KS_EPCR, 0xc);     /* Issue phyxcer read command */
     while(ior(db, DM9KS_EPCR)&0x1);    /* Wait read complete */
     iow(db, DM9KS_EPCR, 0x0);     /* Clear phyxcer read command */
     /* The read data keeps on REG_0D & REG_0E */
     return ( ior(db, DM9KS_EPDRH) <<  ) | ior(db, DM9KS_EPDRL);
 }
 /*
    Write a word to phyxcer
 */
 static void dm9000_phy_write(board_info_t *db, int reg, u16 value)
 {
     /* Fill the phyxcer register into REG_0C */
     iow(db, DM9KS_EPAR, DM9KS_PHY | reg);
     /* Fill the written data into REG_0D & REG_0E */
     iow(db, DM9KS_EPDRL, (value & 0xff));
     iow(db, DM9KS_EPDRH, ( (value >> ) & 0xff));
     iow(db, DM9KS_EPCR, 0xa);    /* Issue phyxcer write command */
     while(ior(db, DM9KS_EPCR)&0x1);    /* Wait read complete */
     iow(db, DM9KS_EPCR, 0x0);    /* Clear phyxcer write command */
 }
 //====dmfe_ethtool_ops member functions====
 static void dmfe_get_drvinfo(struct net_device *dev,
                    struct ethtool_drvinfo *info)
 {
     //board_info_t *db = netdev_priv(dev);
     strcpy(info->driver, DRV_NAME);
     strcpy(info->version, DRV_VERSION);
     sprintf(info->bus_info, "ISA 0x%lx irq=%d",dev->base_addr, dev->irq);
 }
 static int dmfe_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
     board_info_t *db = netdev_priv(dev);
     spin_lock_irq(&db->lock);
     mii_ethtool_gset(&db->mii, cmd);
     spin_unlock_irq(&db->lock);
     return ;
 }
 static int dmfe_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
     board_info_t *db = netdev_priv(dev);
     int rc;
     spin_lock_irq(&db->lock);
     rc = mii_ethtool_sset(&db->mii, cmd);
     spin_unlock_irq(&db->lock);
     return rc;
 }
 /*
 * Check the link state
 */
 static u32 dmfe_get_link(struct net_device *dev)
 {
     board_info_t *db = netdev_priv(dev);
     return mii_link_ok(&db->mii);
 }
 /*
 * Reset Auto-negitiation
 */
 static int dmfe_nway_reset(struct net_device *dev)
 {
     board_info_t *db = netdev_priv(dev);
     return mii_nway_restart(&db->mii);
 }
 //=========================================
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,28)  /* for kernel 2.4.28 */
 static struct ethtool_ops dmfe_ethtool_ops = {
     .get_drvinfo        = dmfe_get_drvinfo,
     .get_settings        = dmfe_get_settings,
     .set_settings        = dmfe_set_settings,
     .get_link            = dmfe_get_link,
     .nway_reset        = dmfe_nway_reset,
     //.get_rx_csum        = dmfe_get_rx_csum,
     //.set_rx_csum        = dmfe_set_rx_csum,
     //.get_tx_csum        = dmfe_get_tx_csum,
     //.set_tx_csum        = dmfe_set_tx_csum,
 };
 #endif
 //#ifdef MODULE
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Davicom DM9000/DM9010 ISA/uP Fast Ethernet Driver");
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 MODULE_PARM(mode, "i");
 MODULE_PARM(irq, "i");
 MODULE_PARM(iobase, "i");
 #else
 module_param(mode, int, );
 module_param(irq, int, );
 module_param(iobase, int, );
 #endif
 MODULE_PARM_DESC(mode,"Media Speed, 0:10MHD, 1:10MFD, 4:100MHD, 5:100MFD");
 MODULE_PARM_DESC(irq,"EtherLink IRQ number");
 MODULE_PARM_DESC(iobase, "EtherLink I/O base address");
 /* Description:
    when user used insmod to add module, system invoked init_module()
    to initilize and register.
 */
 int __init dm9000c_init(void)
 {
     volatile unsigned long *bwscon; // 0x48000000
     volatile unsigned long *bankcon4; // 0x48000014
     unsigned long val;
     iobase = (int)ioremap(0x20000000, );  /* thisway.diy@163.com */
     irq    = IRQ_EINT7;                  /* thisway.diy@163.com */
     /* 设置S3C2440的memory controller */
     bwscon   = ioremap(0x48000000, );
     bankcon4 = ioremap(0x48000014, );
     /* DW4[17:16]: 01-16bit
      * WS4[18]   : 0-WAIT disable
      * ST4[19]   : 0 = Not using UB/LB (The pins are dedicated nWBE[3:0])
      */
     val = *bwscon;
     val &= ~(0xf<<);
     val |= (<<);
     *bwscon = val;
     /*
      * Tacs[14:13]: 发出片选信号之前,多长时间内要先发出地址信号
      *              DM9000C的片选信号和CMD信号可以同时发出,
      *              所以它设为0
      * Tcos[12:11]: 发出片选信号之后,多长时间才能发出读信号nOE
      *              DM9000C的T1>=0ns,
      *              所以它设为0
      * Tacc[10:8] : 读写信号的脉冲长度,
      *              DM9000C的T2>=10ns,
      *              所以它设为1, 表示2个hclk周期,hclk=100MHz,就是20ns
      * Tcoh[7:6]  : 当读信号nOE变为高电平后,片选信号还要维持多长时间
      *              DM9000C进行写操作时, nWE变为高电平之后, 数据线上的数据还要维持最少3ns
      *              DM9000C进行读操作时, nOE变为高电平之后, 数据线上的数据在6ns之内会消失
      *              我们取一个宽松值: 让片选信号在nOE放为高电平后,再维持10ns,
      *              所以设为01
      * Tcah[5:4]  : 当片选信号变为高电平后, 地址信号还要维持多长时间
      *              DM9000C的片选信号和CMD信号可以同时出现,同时消失
      *              所以设为0
      * PMC[1:0]   : 00-正常模式
      *
      */
     *bankcon4 = (<<)|(<<);    /* 对于DM9000C可以设Tacc为1, 对于DM9000E,Tacc要设大一点,比如最大值7  */
     //*bankcon4 = (7<<8)|(1<<6);  /* MINI2440使用DM9000E,Tacc要设大一点 */
     iounmap(bwscon);
     iounmap(bankcon4);
     switch(mode) {
         case DM9KS_10MHD:
         case DM9KS_100MHD:
         case DM9KS_10MFD:
         case DM9KS_100MFD:
             media_mode = mode;
             break;
         default:
             media_mode = DM9KS_AUTO;
     }
     dmfe_dev = dmfe_probe();
     if(IS_ERR(dmfe_dev))
         return PTR_ERR(dmfe_dev);
     return ;
 }
 /* Description:
    when user used rmmod to delete module, system invoked clean_module()
    to  un-register DEVICE.
 */
 void __exit dm9000c_exit(void)
 {
     struct net_device *dev = dmfe_dev;
     DMFE_DBUG(, "clean_module()", );
     unregister_netdev(dmfe_dev);
     release_region(dev->base_addr, );
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
     kfree(dev);
 #else
     free_netdev(dev);
 #endif
     iounmap((void *)iobase);
     DMFE_DBUG(, "clean_module() exit", );
 }
 module_init(dm9000c_init);
 module_exit(dm9000c_exit);
 //#endif
dm9000c 移值新内核 linux-4.1.24的更多相关文章
- s3c2440 移值新内核 linux-4.1.36
		arm-linuxgcc version 4.3.2 经过试验,最高可以编译到 linux-4.1.36 ,在高的版本会有错误 ,可能是 GCC 编译器版本较低造成. 解压比较麻烦还要装一个 xz x ... 
- linux如何编译安装新内核支持NTFS文件系统?(以redhat7.2x64为例)
		内核,是一个操作系统的核心.它负责管理系统的进程.内存.设备驱动程序.文件和网络系统,决定着系统的性能和稳定性.Linux作为一个自由软件,在广大爱好者的支持下,内核版本不断更新.新的内核修订了旧内核 ... 
- linux新内核的freeze框架以及意义【转】
		转自:https://blog.csdn.net/dog250/article/details/5303442 linux的电源管理发展非常迅速,比如在挂起到内存的时候,系统会冻结住所有的进程,也就是 ... 
- linux新内核中关闭硬盘的DMA
		vortex86 SIS550 Minit-5250E瘦客户机,使用CF卡启动,显示不支持DMA. 搜索得新内核已基本不再使用ide=nodma参数了,查到这篇文章:“Debian下关闭CF卡的DMA ... 
- 移值UCOS2到M4核与M3核的区别
		之前移值过ucos2到stm32f2系列的单片机,这个单片机是属于arm的m3内核的.最近在学习永磁同步电机的控制,对于这个电机的控制,有比较多的数学计算,甚至于还有浮点的运算.所以用到了stm32f ... 
- 解决树莓派新内核无法使用18B20和没有声音的问题
		现在新版的树莓派内核由于为了兼容树莓派2和树莓派B+等以前的版本,采用了和原来不同的内核运行方式,使用了设备树的方式,更加灵活.但是由于可能不习惯这样的方式以及没太多相关这方面的介绍,导致很多用户更新 ... 
- 加入新的linux系统调用
		上一篇详解了linux系统调用的原理,接下来依据上一篇的原理简介怎样创建新的linux系统调用 向内核中加入新的系统调用,须要运行3个步骤: 1. 加入新的内核函数 2. 更新头文件unistd.h ... 
- 启动新内核出现:Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004
		转载请注明出处:http://blog.csdn.net/qq_26093511/article/details/51841281 启动新内核出现错误:Kernel panic - not synci ... 
- [转帖]新的Linux后门开始肆虐 主要攻击中国服务器
		新的Linux后门开始肆虐 主要攻击中国服务器 https://www.cnbeta.com/articles/tech/815639.htm 一种新的 Linux 系统后门已经开始肆虐,并主要运行在 ... 
随机推荐
- [转载] Win7KB3146706补丁导致蓝屏0x0000006B的修复方案
			进入winpe,将附件的蓝屏6B修复补丁kb3146706.zip的补丁替换windows/system32下面的ci.dll文件,里面有64和32位系统的,替换了文件就可以进入系统了. 启动进入系统 ... 
- Solr Python API : SolrCloudpy 与 Pysolr 的 对比
			http://ae.yyuap.com/pages/viewpage.action?pageId=920314 SolrCloudpy文档:http://solrcloudpy.github.io/s ... 
- PHP preg_replace使用例子
			将 qwer://xxx/545/0 替换为 qwer://trading_system_xxx/0/545 $str = '<a href="qwer://xxx/545/0&quo ... 
- erlang ssl
			http://itindex.net/detail/50701-tomcat-bio-nio.apr http://blog.csdn.net/libing1991_/article/details/ ... 
- JQ first-child与:first的区别以及nth-child(index)与eq(index)的区别
			1.first-child和:first区别 first-child 是指选取每个父元素的第一个子元素 如$("div:first-child")指每个父级里的第一个div孩子 ... 
- zookeeper+jstorm的集群搭建
			zookeeper的配置: zookeeper有三种配置方式:单机式/伪分布式/集群式 其中伪分布式是在一台电脑上通过不同的端口来模拟分布式情形,需要N份配置文件和启动程序,而集群式是多个zookee ... 
- android中如何在低版本(5.0之前)上使用tint(着色)属性
			1. 使用app前缀(app:backgroundTint,app:backgroundTintMode),如果使用android前缀,在低版本上是拿不到值的,因为这些属性是5.0以后才加入的. 2. ... 
- 基于 Token 的身份验证方法
			使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录.大概的流程是这样的: 客户端使用用户名跟密码请求登录 服务端收到请求,去验证用户名与密码 验证成功后,服务端会签发一个 Toke ... 
- JDK1.8导致发送邮件失败
			问题:本地JDK1.6测试可以发送邮件,但是linux上jdk1.8发送邮件失败.报错: Sending the email to the following server failed : smtp ... 
- Emphasis on Filtering & Depth Map Occlusion Filling
			http://people.clarkson.edu/~hudsonb/courses/cs611/ 
