   looking for driver for linux
  Looking for drivers for:BP PLL E186014PN: 1242-0000115-020i got a decompiled one here:static const char *version ="fealnx.c:v2.20 9/1/00\n";static const char *version1 ="   http://cesdis.gsfc.nasa.gov/linux/drivers/ethercard.html\n";static int debug=0;/* 1-> print debug message */static int max_interrupt_work = 20;static int min_pci_latency = 32;/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). */static int multicast_filter_limit = 32;/* Set the copy breakpoint for the copy-only-tiny-frames scheme. *//* Setting to > 1518 effectively disables this feature.*/static int rx_copybreak = 0;/* Used to pass the media type, etc.   *//* Both 'options[]' and 'full_duplex[]' should exist for driver *//* interoperability.    *//* The media type is usually passed in 'options[]'.   */#define MAX_UNITS 8/* More are supported, limit only on options */static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};/* Operational parameters that are set at compile time.  *//* Keep the ring sizes a power of two for compile efficiency. *//* The compiler will convert <unsigned>'%'<2^N> into a bit mask.   *//* Making the Tx ring too large decreases the effectiveness of channel  *//* bonding and packet priority. *//* There are no ill effects from too-large receive rings.*/// 88-12-9 modify,// #define TX_RING_SIZE    16// #define RX_RING_SIZE    32#define TX_RING_SIZE    6#define RX_RING_SIZE    12/* Operational parameters that usually are not changed. *//* Time in jiffies before concluding the transmitter is hung. */#define TX_TIMEOUT (2*HZ)#define PKT_BUF_SZ 1536    /* Size of each temporary Rx buffer.*//* Include files, designed to support most kernel versions 2.0.0 and later. */#include <linux/config.h>#include <linux/version.h>#ifdef MODULE#ifdef MODVERSIONS#include <linux/modversions.h>#endif#include <linux/module.h>#else#define MOD_INC_USE_COUNT#define MOD_DEC_USE_COUNT#endif#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/malloc.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <asm/processor.h> /* Processor type for cache alignment. */#include <asm/bitops.h>#include <asm/io.h>/* This driver was written to use PCI memory space, however some x86 systems   work only with I/O space accesses. */#ifndef __alpha__#define USE_IO#endif#ifdef USE_IO#undef readb#undef readw#undef readl#undef writeb#undef writew#undef writel#define readb inb#define readw inw#define readl inl#define writeb outb#define writew outw#define writel outl#endif/* Kernel compatibility defines, some common to David Hinds' PCMCIA package. *//* This is only in the support-all-kernels source code. */#define RUN_AT(x) (jiffies + (x))#if (LINUX_VERSION_CODE >= 0x20100)char kernel_version[] = UTS_RELEASE;#else#ifndef __alpha__#define ioremap vremap#define iounmap vfree#endif#endif#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115MODULE_AUTHOR("Jao Ching Chen");MODULE_DESCRIPTION("100/10M Ethernet PCI Driver");MODULE_PARM(max_interrupt_work, "i");MODULE_PARM(min_pci_latency, "i");MODULE_PARM(debug, "i");MODULE_PARM(rx_copybreak, "i");MODULE_PARM(multicast_filter_limit, "i");MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");#endif#if LINUX_VERSION_CODE < 0x20123#define test_and_set_bit(val, addr) set_bit(val, addr)#endif#if LINUX_VERSION_CODE <= 0x20139#define net_device_stats enet_statistics#else#define NETSTATS_VER2#endif#if LINUX_VERSION_CODE < 0x20155  ||  defined(CARDBUS)/* Grrrr, the PCI code changed, but did not consider CardBus... */#include <linux/bios32.h>#define PCI_SUPPORT_VER1#else#define PCI_SUPPORT_VER2#endif#if LINUX_VERSION_CODE < 0x20159#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE);#else#define dev_free_skb(skb) dev_kfree_skb(skb);#endif/* PCI probe table. */static struct device *fealnx_probe1(int pci_bus, int devfn, struct device *dev,    long ioaddr, int irq, int chp_idx,    int fnd_cnt);#ifdef USE_IO#define fealnx_FLAGS (PCI_USES_IO | PCI_ADDR0 | PCI_USES_MASTER)#else#define fealnx_FLAGS (PCI_USES_MEM | PCI_ADDR1 | PCI_USES_MASTER)#endifenum pci_flags_bit {   PCI_USES_IO=1,   PCI_USES_MEM=2,   PCI_USES_MASTER=4,   PCI_ADDR0=0x10<<0,   PCI_ADDR1=0x10<<1,   PCI_ADDR2=0x10<<2,   PCI_ADDR3=0x10<<3,};struct pci_id_info {   const char *name;   u16 vendor_id, device_id, device_id_mask, flags;   int io_size;   struct device *(*probe1)(int pci_bus, int pci_devfn,   struct device *dev, long ioaddr, int irq,   int chip_idx, int fnd_cnt);};static struct pci_id_info pci_tbl[] = {   {"MTD800", 0x1516, 0x0800, 0xffff,   /* NIC only */    fealnx_FLAGS, 136, fealnx_probe1},   {"MTD803", 0x1516, 0x0803, 0xffff,   /* 3-in-1 */    fealnx_FLAGS, 136, fealnx_probe1},   {"MTD891", 0x1516, 0x0891, 0xffff,   /* G-bit */    fealnx_FLAGS, 136, fealnx_probe1},   {0,},   /* 0 terminated list. */};/* A chip capabilities table, matching the entries in pci_tbl[] above. */enum chip_capability_flags {   HAS_MII_XCVR,   HAS_CHIP_XCVR,};/* 89/6/13 add, *//* for different PHY */enum phy_type_flags {   PHY=1,   AhdocPHY=2,   SeeqPHY=3,   MarvellPHY=4,   MTD981=5,   OtherPHY=10,};struct chip_info {   char *chip_name;   int io_size;   int flags;   void (*media_timer)(unsigned long data);};static struct chip_info skel_netdrv_tbl[] = {   {"100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR, },   {"100/10M Ethernet PCI Adapter", 136, HAS_CHIP_XCVR, },   {"1000/100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR, },};/* Offsets to the Command and Status Registers. */enum fealnx_offsets {   PAR0=0x0,/* physical address 0-3 */   PAR1=0x04,    /* physical address 4-5 */   MAR0=0x08,    /* multicast address 0-3 */   MAR1=0x0C,    /* multicast address 4-7 */   FAR0=0x10,    /* flow-control address 0-3 */   FAR1=0x14,    /* flow-control address 4-5 */   TCRRCR=0x18,  /* receive & transmit configuration */   BCR=0x1C,/* bus command */   TXPDR=0x20,   /* transmit polling demand */   RXPDR=0x24,   /* receive polling demand */   RXCWP=0x28,   /* receive current word pointer */   TXLBA=0x2C,   /* transmit list base address */   RXLBA=0x30,   /* receive list base address */   ISR=0x34,/* interrupt status */   IMR=0x38,/* interrupt mask */   FTH=0x3C,/* flow control high/low threshold */   MANAGEMENT=0x40,   /* bootrom/eeprom and mii management */   TALLY=0x44,   /* tally counters for crc and mpa */   TSR=0x48,/* tally counter for transmit status */   BMCRSR=0x4c,  /* basic mode control and status */   PHYIDENTIFIER=0x50,/* phy identifier */   ANARANLPAR=0x54,   /* auto-negotiation advertisement and linkpartner ability */   ANEROCR=0x58, /* auto-negotiation expansion and pci conf. */   BPREMRPSR=0x5c,    /* bypass & receive error mask and phy status */};/* Bits in the interrupt status/enable registers. *//* The bits in the Intr Status/Enable registers, mostly interrupt sources. */enum intr_status_bits {   RFCON=0x00020000,  /* receive flow control xon packet */   RFCOFF=0x00010000, /* receive flow control xoff packet */   LSCStatus=0x00008000,   /* link status change */   ANCStatus=0x00004000,   /* autonegotiation completed */   FBE=0x00002000,    /* fatal bus error */   FBEMask=0x00001800,/* mask bit12-11 */   ParityErr=0x00000000,   /* parity error */   TargetErr=0x00001000,   /* target abort */   MasterErr=0x00000800,   /* master error */   TUNF=0x00000400,   /* transmit underflow */   ROVF=0x00000200,   /* receive overflow */   ETI=0x00000100,    /* transmit early int */   ERI=0x00000080,    /* receive early int */   CNTOVF=0x00000040, /* counter overflow */   RBU=0x00000020,    /* receive buffer unavailable */   TBU=0x00000010,    /* transmit buffer unavilable */   TI=0x00000008,/* transmit interrupt */   RI=0x00000004,/* receive interrupt */   RxErr=0x00000002,  /* receive error */};/* Bits in the NetworkConfig register. */enum rx_mode_bits {   RxModeMask=0xe0,   PROM=0x80, /* promiscuous mode */   AB=0x40,   /* accept broadcast */   AM=0x20,   /* accept mutlicast */   ARP=0x08,  /* receive runt pkt */   ALP=0x04,  /* receive long pkt */   SEP=0x02,  /* receive error pkt */};/* The Tulip Rx and Tx buffer descriptors. */struct fealnx_desc {   s32 status;   s32 control;   u32 buffer;   u32 next_desc;   struct fealnx_desc *next_desc_logical;   struct sk_buff *skbuff;   u32 reserved1;   u32 reserved2;};/* Bits in network_desc.status */enum rx_desc_status_bits {   RXOWN=0x80000000,  /* own bit */   FLNGMASK=0x0fff0000,    /* frame length */   FLNGShift=16,   MARSTATUS=0x00004000,   /* multicast address received */   BARSTATUS=0x00002000,   /* broadcast address received */   PHYSTATUS=0x00001000,   /* physical address received */   RXFSD=0x00000800,  /* first descriptor */   RXLSD=0x00000400,  /* last descriptor */   ErrorSummary=0x80, /* error summary */   RUNT=0x40,    /* runt packet received */   LONG=0x20,    /* long packet received */   FAE=0x10,/* frame align error */   CRC=0x08,/* crc error */   RXER=0x04,    /* receive error */};enum rx_desc_control_bits {   RXIC=0x00800000,   /* interrupt control */   RBSShift=0,};enum tx_desc_status_bits {   TXOWN=0x80000000,  /* own bit */   JABTO=0x00004000,  /* jabber timeout */   CSL=0x00002000,    /* carrier sense lost */   LC=0x00001000,/* late collision */   EC=0x00000800,/* excessive collision */   UDF=0x00000400,    /* fifo underflow */   DFR=0x00000200,    /* deferred */   HF=0x00000100,/* heartbeat fail */   NCRMask=0x000000ff,/* collision retry count */   NCRShift=0,};enum tx_desc_control_bits {   TXIC=0x80000000, /* interrupt control */   ETIControl=0x40000000,/* early transmit interrupt */   TXLD=0x20000000, /* last descriptor */   TXFD=0x10000000, /* first descriptor */   CRCEnable=0x08000000, /* crc control */   PADEnable=0x04000000, /* padding control */   PKTSMask=0x3ff800,    /* packet size bit21-11 */   PKTSShift=11,   TBSMask=0x000007ff,   /* transmit buffer bit 10-0 */   TBSShift=0,};/* BootROM/EEPROM/MII Management Register */#define MASK_MIIR_MII_READ  0x00000000#define MASK_MIIR_MII_WRITE 0x00000008#define MASK_MIIR_MII_MDO   0x00000004#define MASK_MIIR_MII_MDI   0x00000002#define MASK_MIIR_MII_MDC   0x00000001/* ST+OP+PHYAD+REGAD+TA */#define OP_READ   0x6000 /* ST:01+OP:10+PHYAD+REGAD+TA:Z0 */#define OP_WRITE  0x5002 /* ST:01+OP:01+PHYAD+REGAD+TA:10 *//* ------------------------------------------------------------------------- *//* Constants for PHY  *//* ------------------------------------------------------------------------- */#define PHYID 0xd0000302/* 89-7-27 add, (begin) */#define PHYID00x0302#define StatusRegister  18#define SPEED100   0x0400 // bit10#define FULLMODE   0x0800 // bit11/* 89-7-27 add, (end) *//* ------------------------------------------------------------------------- *//* Constants for Seeq 80225 PHY *//* ------------------------------------------------------------------------- */#define SeeqPHYID0 0x0016#define MIIRegister18   18#define SPD_DET_1000x80#define DPLX_DET_FULL   0x40/* ------------------------------------------------------------------------- *//* Constants for Ahdoc 101 PHY  *//* ------------------------------------------------------------------------- */#define AhdocPHYID00x0022#define DiagnosticReg   18#define DPLX_FULL  0x0800#define Speed_100  0x0400/* 89/6/13 add, *//* -------------------------------------------------------------------------- *//* Constants *//* -------------------------------------------------------------------------- */#define MarvellPHYID0 0x0141#define MII1000BaseTControlReg  9#define MII1000BaseTStatusReg   10/* for 1000BaseT Control Register */#define PHYAbletoPerform1000FullDuplex  0x0200#define PHYAbletoPerform1000HalfDuplex  0x0100#define PHY1000AbilityMask    0x300#define SpecificReg17#define SpeedMask  0x0c000#define Speed_1000M0x08000#define Speed_100M 0x4000#define Speed_10M  0#define Full_Duplex0x2000/* for 3-in-1 case */#define PS10  0x00080000#define FD    0x00100000#define PS10000x00010000#define LinkIsUp20x00040000/* for PHY */#define LinkIsUp   0x0004struct netdev_private {   /* Descriptor rings first for alignment. */   struct fealnx_desc rx_ring[RX_RING_SIZE];   struct fealnx_desc tx_ring[TX_RING_SIZE];   /* Link for devices of this type. */   struct device *next_module;   const char *product_name;   struct net_device_stats stats;   /* Media monitoring timer. */   struct timer_list timer;   /* Frequently used values: keep some adjacent for cache effect. */   int chip_id;   int flags;   unsigned char pci_bus, pci_devfn;   unsigned long crvalue;   unsigned long bcrvalue;   struct fealnx_desc *cur_rx;   struct fealnx_desc *lack_rxbuf;   int really_rx_count;   struct fealnx_desc *cur_tx;   struct fealnx_desc *cur_tx_copy;   int really_tx_count;   int free_tx_count;   unsigned int rx_buf_sz;    /* Based on MTU+slack. */   /* These values are keep track of the transceiver/media in use. */   unsigned int linkok;   unsigned int line_speed;   unsigned int duplexmode;   unsigned int full_duplex:1;/* Full-duplex operation requested. */   unsigned int duplex_lock:1;   unsigned int medialock:1;  /* Do not sense media. */   unsigned int default_port:4;    /* Last dev->if_port value. */   unsigned int PHYType;   /* MII transceiver section. */   int mii_cnt;/* MII device addresses. */   unsigned char phys[2];/* MII device addresses. */   u32 pad[4]; /* Used for 32-byte alignment */};static uint mdio_read(struct device *dev, int phy_id, int location);static void mdio_write(struct device *dev, int phy_id, int location,  int value);static int  netdev_open(struct device *dev);static void getlinktype(struct device *dev);static void getlinkstatus(struct device *dev);static void netdev_timer(unsigned long data);static void tx_timeout(struct device *dev);static void init_ring(struct device *dev);static int  start_tx(struct sk_buff *skb, struct device *dev);static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs);static int  netdev_rx(struct device *dev);static inline unsigned ether_crc(int length, unsigned char *data);static void set_rx_mode(struct device *dev);static struct net_device_stats *get_stats(struct device *dev);static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd);static int netdev_close(struct device *dev);void stop_nic_tx(long ioaddr, long crvalue){   writel(crvalue & (~0x40000), ioaddr+TCRRCR);   /* wait for tx stop */   { int i=0, delay=0x1000; while ( (!(readl(ioaddr+TCRRCR)&0x04000000)) && (i<delay) ) {    ++i; }   }}void stop_nic_rx(long ioaddr, long crvalue){   writel(crvalue & (~0x1), ioaddr+TCRRCR);   /* wait for rx stop */   { int i=0, delay=0x1000; while ( (!(readl(ioaddr+TCRRCR)&0x00008000)) && (i<delay) ) {    ++i; }   }}/* A list of our installed devices, for removing the driver module. */static struct device *root_net_dev = NULL;/* Ideally we would detect all network cards in slot order.  That would   be best done a central PCI probe dispatch, which wouldn't work   well when dynamically adding drivers.  So instead we detect just the   cards we know about in slot order. */static int pci_etherdev_probe(struct device *dev,struct pci_id_info pci_tbl[]){   int cards_found = 0;   int pci_index = 0;   unsigned char pci_bus, pci_device_fn;   if (!pcibios_present())return -ENODEV;   for (;pci_index < 0xff; pci_index++)   { u16 vendor, device, pci_command, new_command; int chip_idx, irq; long pciaddr; long ioaddr; if (pcibios_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,    &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL)   break; pcibios_read_config_word(pci_bus, pci_device_fn, PCI_VENDOR_ID, &vendor); pcibios_read_config_word(pci_bus, pci_device_fn, PCI_DEVICE_ID, &device); for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)   if (vendor == pci_tbl[chip_idx].vendor_id  && (device & pci_tbl[chip_idx].device_id_mask) == pci_tbl[chip_idx].device_id)break; if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */   continue; /* get the system resources, IO/Memory Address, IRQ */ {#if defined(PCI_SUPPORT_VER2)    struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);#ifdef USE_IO    pciaddr = pdev->base_address[0] & ~3;#else    pciaddr = pdev->base_address[1];#endif    irq = pdev->irq;#else    u32 pci_memaddr;    u8 pci_irq_line;    pcibios_read_config_byte(pci_bus, pci_device_fn,    PCI_INTERRUPT_LINE, &pci_irq_line);#ifdef USE_IO    pcibios_read_config_dword(pci_bus, pci_device_fn,PCI_BASE_ADDRESS_0, &pci_memaddr);    pciaddr = pci_memaddr & ~1;#else    pcibios_read_config_dword(pci_bus, pci_device_fn,PCI_BASE_ADDRESS_1, &pci_memaddr);    pciaddr = pci_memaddr;#endif    irq = pci_irq_line;#endif } if ((pci_tbl[chip_idx].flags & PCI_USES_IO)) {  /* use I/O access method */    if (check_region(pciaddr, pci_tbl[chip_idx].io_size)) continue;    ioaddr = pciaddr; } else {  /* use memory access method */    if ((ioaddr = (long)ioremap(pciaddr & ~0xf, 0x400)) == 0)    {  printk(KERN_INFO "Failed to map PCI address %#lx.\n", pciaddr);  continue;    } } /* check the command register */ pcibios_read_config_word(pci_bus, pci_device_fn, PCI_COMMAND, &pci_command); new_command = pci_command | (pci_tbl[chip_idx].flags & 7); if (pci_command != new_command) {    printk(KERN_INFO "  The PCI BIOS has not enabled the" " device at %d/%d!  Updating PCI command %4.4x->%4.4x.\n", pci_bus, pci_device_fn, pci_command, new_command);    pcibios_write_config_word(pci_bus, pci_device_fn, PCI_COMMAND,new_command); } dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr,  irq, chip_idx, cards_found); /* check the latency value */ if (dev  && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) {    u8 pci_latency;    pcibios_read_config_byte(pci_bus, pci_device_fn,    PCI_LATENCY_TIMER, &pci_latency);    if (pci_latency < min_pci_latency)    {  printk(KERN_INFO "  PCI latency timer (CFLT) is "    "unreasonably low at %d.  Setting to %d clocks.\n",    pci_latency, min_pci_latency);  pcibios_write_config_byte(pci_bus, pci_device_fn,   PCI_LATENCY_TIMER, min_pci_latency);    } } dev = 0; cards_found++;   }  /* end of for loop */   return cards_found ? 0 : -ENODEV;}static struct device *fealnx_probe1(int pci_bus, int devfn, struct device *dev,    long ioaddr, int irq, int chip_id,    int card_idx){   struct netdev_private *np;   int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0;   dev = init_etherdev(dev, sizeof(struct netdev_private));   printk(KERN_INFO "%s: %s at 0x%lx, ",dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr);   /* read ethernet id */   for (i=0;i<6;++i)dev->dev_addr=readb(ioaddr+PAR0+i);   for (i = 0; i < 5; i++)printk("%2.2x:", dev->dev_addr);   printk("%2.2x, IRQ %d.\n", dev->dev_addr, irq);#ifdef USE_IO   request_region(ioaddr, pci_tbl[chip_id].io_size, dev->name);#endif   /* Reset the chip to erase previous misconfiguration. */   writel(0x00000001, ioaddr + BCR);   dev->base_addr = ioaddr;   dev->irq = irq;   /* Make certain the descriptor lists are aligned. */   np = (void *)(((long)kmalloc(sizeof(*np), GFP_KERNEL) + 15) & ~15);   memset(np, 0, sizeof(*np));   dev->priv = np;   np->next_module = root_net_dev;   root_net_dev = dev;   np->pci_bus = pci_bus;   np->pci_devfn = devfn;   np->chip_id = chip_id;   np->flags = skel_netdrv_tbl[np->chip_id].flags;   /* find the connected MII xcvrs */   if (np->flags==HAS_MII_XCVR)   { int phy, phy_idx = 0; for (phy = 1; phy < 32 && phy_idx < 4; phy++) {    int mii_status = mdio_read(dev, phy, 1);    if (mii_status != 0xffff  &&  mii_status != 0x0000)    {  np->phys[phy_idx++] = phy;  printk(KERN_INFO "%s: MII PHY found at address %d, status "    "0x%4.4x.\n",    dev->name, phy, mii_status);  /* get phy type */  {unsigned int data;data=mdio_read(dev, np->phys[0], 2);if (data==SeeqPHYID0)  np->PHYType=SeeqPHY;else if (data==AhdocPHYID0)  np->PHYType=AhdocPHY;else if (data==MarvellPHYID0)  np->PHYType=MarvellPHY;else if (data==PHYID0)  np->PHYType=MTD981;else  np->PHYType=OtherPHY;  }    } } np->mii_cnt = phy_idx; if (phy_idx == 0) {    printk(KERN_WARNING "%s: MII PHY not found -- this device may " "not operate correctly.\n", dev->name); }   }   else   { np->phys[0] = 32;/* 89/6/23 add, (begin) */ /* get phy type */ if (readl(dev->base_addr+PHYIDENTIFIER)==PHYID)   np->PHYType=PHY; else   np->PHYType=OtherPHY;   }   if (dev->mem_start)option = dev->mem_start;   /* The lower four bits are the media type. */   if (option > 0)   { if (option & 0x200)   np->full_duplex = 1; np->default_port = option & 15; if (np->default_port)   np->medialock = 1;   }   if (card_idx < MAX_UNITS  &&  full_duplex[card_idx] > 0)np->full_duplex = full_duplex[card_idx];   if (np->full_duplex)   { printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);/* 89/6/13 add, (begin) */ if (np->PHYType==MarvellPHY) {    unsigned int data;    data=mdio_read(dev, np->phys[0], 9);    data=(data&0xfcff)|0x0200;    mdio_write(dev, np->phys[0], 9, data); }/* 89/6/13 add, (end) */ if (np->flags==HAS_MII_XCVR)   mdio_write(dev, np->phys[0], 4, 0x141); else   writel(0x141, dev->base_addr+ANARANLPAR); np->duplex_lock = 1;   }   /* The chip-specific entries in the device structure. */   dev->open = &netdev_open;   dev->hard_start_xmit = &start_tx;   dev->stop = &netdev_close;   dev->get_stats = &get_stats;   dev->set_multicast_list = &set_rx_mode;   dev->do_ioctl = &mii_ioctl;   return dev;}uint m80x_read_tick()/* function: Reads the Timer tick count register which decrements by 2 from  *//* 65536 to 0 every 1/36.414 of a second. Each 2 decrements of the */ /* count represents 838 nsec's. *//* input   : none.    *//* output  : none.    */{   unsigned char tmp;   int value;   writeb((char)0x06, 0x43); // Command 8254 to latch T0's count   // now read the count.   tmp=(unsigned char)readb(0x40);   value=((int)tmp)<<8;   tmp=(unsigned char)readb(0x40);   value|=(((int)tmp)&0xff);   return (value);}void m80x_delay(uint interval)/* function: to wait for a specified time.*//* input   : interval ... the specified time.  *//* output  : none.    */{   uint interval1, interval2, i=0;   interval1=m80x_read_tick(); // get initial value   do   { interval2=m80x_read_tick(); if (interval1<interval2)   interval1=interval2; ++i;   } while ( ((interval1-interval2)<(ushort)interval)&&(i<65535) );}static ulong m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad){   ulong miir;   int  i;   uint mask, data;   /* enable MII output */   miir=(ulong)readl(miiport);   miir&=0xfffffff0;   miir|=MASK_MIIR_MII_WRITE+MASK_MIIR_MII_MDO;   /* send 32 1's preamble */   for (i=0;i<32;i++)   { /* low MDC; MDO is already high (miir) */ miir&=~MASK_MIIR_MII_MDC; writel(miir, miiport); /* high MDC */ miir|=MASK_MIIR_MII_MDC; writel(miir, miiport);   }   /* calculate ST+OP+PHYAD+REGAD+TA */   data=opcode|(phyad<<7)|(regad<<2);   /* sent out */   mask=0x8000;   while (mask)   { /* low MDC, prepare MDO */ miir&=~(MASK_MIIR_MII_MDC+MASK_MIIR_MII_MDO); if (mask & data)   miir|=MASK_MIIR_MII_MDO; writel(miir, miiport); /* high MDC */ miir|=MASK_MIIR_MII_MDC; writel(miir, miiport); m80x_delay(30); /* next */ mask>>=1; if (mask==0x2 && opcode==OP_READ)   miir&=~MASK_MIIR_MII_WRITE;   }   return miir;}static uint mdio_read(struct device *dev, int phyad, int regad){   long miiport = dev->base_addr + MANAGEMENT;   ulong miir;   uint mask, data;   miir=m80x_send_cmd_to_phy(miiport, OP_READ, phyad, regad);   /* read data */   mask=0x8000;   data=0;   while (mask)   { /* low MDC */ miir&=~MASK_MIIR_MII_MDC; writel(miir, miiport); /* read MDI */ miir=readl(miiport); if (miir & MASK_MIIR_MII_MDI)   data|=mask; /* high MDC, and wait */ miir|=MASK_MIIR_MII_MDC; writel(miir, miiport); m80x_delay((int)30); /* next */ mask>>=1;   }   /* low MDC */   miir&=~MASK_MIIR_MII_MDC;   writel(miir, miiport);   return data;}static void mdio_write(struct device *dev, int phyad, int regad, int data){   long miiport = dev->base_addr + MANAGEMENT;   ulong miir;   uint mask;   miir=m80x_send_cmd_to_phy(miiport, OP_WRITE, phyad, regad);   /* write data */   mask=0x8000;   while (mask)   { /* low MDC, prepare MDO */ miir&=~(MASK_MIIR_MII_MDC+MASK_MIIR_MII_MDO); if (mask&data)   miir|=MASK_MIIR_MII_MDO; writel(miir, miiport); /* high MDC */ miir|=MASK_MIIR_MII_MDC; writel(miir, miiport); /* next */ mask>>=1;   }   /* low MDC */   miir&=~MASK_MIIR_MII_MDC;   writel(miir, miiport);   return;}static int netdev_open(struct device *dev){   struct netdev_private *np = (struct netdev_private *)dev->priv;   long ioaddr = dev->base_addr;   writel(0x00000001, ioaddr + BCR);    /* Reset */   if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev))return -EAGAIN;   MOD_INC_USE_COUNT;   init_ring(dev);   writel(virt_to_bus(np->rx_ring), ioaddr + RXLBA);   writel(virt_to_bus(np->tx_ring), ioaddr + TXLBA);   /* Initialize other registers. */   /* Configure the PCI bus bursts and FIFO thresholds. 486: Set 8 longword burst. 586: no burst limit. Burst length 5:3 0 0 0   1 0 0 1   4 0 1 0   8 0 1 1   16 1 0 0   32 1 0 1   64 1 1 0   128 1 1 1   256 Wait the specified 50 PCI cycles after a reset by initializing Tx and Rx queues and the address filter list. */#if defined(__powerpc__)// 89/9/1 modify, //   np->bcrvalue=0x04 | 0x0x38;  /* big-endian, 256 burst length */   np->bcrvalue=0x04 | 0x0x10;  /* big-endian, tx 8 burst length */a   np->cralue=0xe00;  /* rx 128 burst length */   #elif defined(__alpha__)// 89/9/1 modify, //   np->bcrvalue=0x38; /* little-endian, 256 burst length */   np->bcrvalue=0x10; /* little-endian, 8 burst length */   np->cralue=0xe00;  /* rx 128 burst length */   #elif defined(__i386__)#if defined(MODULE)// 89/9/1 modify, //   np->bcrvalue=0x38; /* little-endian, 256 burst length */   np->bcrvalue=0x10; /* little-endian, 8 burst length */   np->crvalue=0xe00;  /* rx 128 burst length */   #else   /* When not a module we can work around broken '486 PCI boards. */#if (LINUX_VERSION_CODE > 0x2014c)#define x86 boot_cpu_data.x86#endif// 89/9/1 modify, //   np->bcrvalue=(x86 <= 4 ? 0x10 : 0x38);   np->bcrvalue=0x10;   np->crvalue=(x86 <= 4 ? 0xa00 : 0xe00);   if (x86 <= 4)printk(KERN_INFO "%s: This is a 386/486 PCI system, setting burst "  "length to %x.\n", dev->name, (x86 <= 4 ? 0x10 : 0x38));#endif#else// 89/9/1 modify,//   np->bcrvalue=0x38;   np->bcrvalue=0x10;   np->cralue=0xe00;  /* rx 128 burst length */   #warning Processor architecture undefined!#endif   writel(np->bcrvalue, ioaddr + BCR);   if (dev->if_port == 0)dev->if_port = np->default_port;   dev->interrupt = 0;   writel(0, dev->base_addr + RXPDR);// 89/9/1 modify,//   np->crvalue = 0x00e40001;    /* tx store and forward, tx/rx enable */   np->crvalue |= 0x00e40001;    /* tx store and forward, tx/rx enable */   np->full_duplex = np->duplex_lock;   getlinkstatus(dev);   if (np->linkok)getlinktype(dev);   set_rx_mode(dev);   dev->start = 1;   /* Clear and Enable interrupts by setting the interrupt mask. */   writel(FBE|TUNF|CNTOVF|RBU|TI|RI, ioaddr + ISR);   writel(FBE|TUNF|CNTOVF|RBU|TI|RI, ioaddr + IMR);   if (debug)printk(KERN_DEBUG "%s: Done netdev_open().\n", dev->name);   /* Set the timer to check for link beat. */   init_timer(&np->timer);   np->timer.expires = RUN_AT(3*HZ);   np->timer.data = (unsigned long)dev;   np->timer.function = &netdev_timer;   /* timer handler */   add_timer(&np->timer);   return 0;}static void getlinkstatus(struct device *dev)/* function: Routine will read MII Status Register to get link status.  *//* input   : dev... pointer to the adapter block.   *//* output  : none.    */{   struct netdev_private *np = (struct netdev_private *)dev->priv;   uint i, DelayTime=0x1000;   np->linkok=0;   if (np->PHYType==PHY)   { for (i=0;i<DelayTime;++i) {    if (readl(dev->base_addr+BMCRSR)&LinkIsUp2)    {  np->linkok=1;  return;    }    // delay    m80x_delay(100); }   }   else   { for (i=0;i<DelayTime;++i) {    if (mdio_read(dev, np->phys[0], 1)&0x4)    {  np->linkok=1;  return;    }    // delay    m80x_delay(100); }   }}static void getlinktype(struct device *dev){   struct netdev_private *np = (struct netdev_private *)dev->priv;   if (np->PHYType==PHY)   {  /* 3-in-1 case */ if (readl(dev->base_addr+TCRRCR)&FD)   np->duplexmode=2;  /* full duplex */ else   np->duplexmode=1;  /* half duplex */ if (readl(dev->base_addr+TCRRCR)&PS10)   np->line_speed=1;  /* 10M */ else   np->line_speed=2;  /* 100M */   }   else   { if (np->PHYType==SeeqPHY) {  /* this PHY is SEEQ 80225 */    uint data;   data=mdio_read(dev, np->phys[0], MIIRegister18);    if (data & SPD_DET_100) np->line_speed=2;/* 100M */    else np->line_speed=1;/* 10M */    if (data & DPLX_DET_FULL) np->duplexmode=2;  /* full duplex mode */    else np->duplexmode=1;  /* half duplex mode */ } else if (np->PHYType==AhdocPHY) {    uint data;    data=mdio_read(dev, np->phys[0], DiagnosticReg);    if (data & Speed_100) np->line_speed=2;/* 100M */    else np->line_speed=1;/* 10M */    if (data & DPLX_FULL) np->duplexmode=2;  /* full duplex mode */    else np->duplexmode=1;  /* half duplex mode */ }/* 89/6/13 add, (begin) */ else if (np->PHYType==MarvellPHY) {    uint data;    data=mdio_read(dev, np->phys[0], SpecificReg);    if (data & Full_Duplex) np->duplexmode=2;  /* full duplex mode */    else np->duplexmode=1;  /* half duplex mode */    data&=SpeedMask;    if (data==Speed_1000M) np->line_speed=3;/* 1000M */    else if (data==Speed_100M) np->line_speed=2;/* 100M */    else np->line_speed=1;/* 10M */ }/* 89/6/13 add, (end) *//* 89/7/27 add, (begin) */ else if (np->PHYType==MTD981) {    uint data;    data=mdio_read(dev, np->phys[0], StatusRegister);    if (data & SPEED100) np->line_speed=2;    else  np->line_speed=1;    if (data & FULLMODE) np->duplexmode=2;    else np->duplexmode=1; }/* 89/7/27 add, (end) */ // chage crvalue   // np->crvalue&=(~PS10)&(~FD); np->crvalue&=(~PS10)&(~FD)&(~PS1000); if (np->line_speed==1)   np->crvalue|=PS10; else if (np->line_speed==3)   np->crvalue|=PS1000; if (np->duplexmode==2)   np->crvalue|=FD;   }}static void allocate_rx_buffers(struct device *dev){   struct netdev_private *np = (struct netdev_private *)dev->priv;   /*  allocate skb for rx buffers */   while (np->really_rx_count!=RX_RING_SIZE)   { struct sk_buff *skb; skb = dev_alloc_skb(np->rx_buf_sz); np->lack_rxbuf->skbuff = skb; if (skb == NULL)   break;/* Better luck next round. */ skb->dev = dev;   /* Mark as being used by this device. */ np->lack_rxbuf->buffer = virt_to_bus(skb->tail); np->lack_rxbuf = np->lack_rxbuf->next_desc_logical; ++np->really_rx_count;   }}static void netdev_timer(unsigned long data){   struct device *dev = (struct device *)data;   struct netdev_private *np = (struct netdev_private *)dev->priv;   long ioaddr = dev->base_addr;   int next_tick = 10*HZ;   int old_crvalue=np->crvalue;   unsigned int old_linkok=np->linkok;   if (debug)printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x "  "config %8.8x.\n", dev->name, readl(ioaddr + ISR),  readl(ioaddr + TCRRCR));   if (np->flags==HAS_MII_XCVR)   { getlinkstatus(dev); if ((old_linkok==0)&&(np->linkok==1)) {  /* we need to detect the media type again */    getlinktype(dev);    if (np->crvalue != old_crvalue)    {  stop_nic_tx(ioaddr, np->crvalue);  stop_nic_rx(ioaddr, np->crvalue&(~0x40000));  writel(np->crvalue, ioaddr + TCRRCR);    } }   }   allocate_rx_buffers(dev);   np->timer.expires = RUN_AT(next_tick);   add_timer(&np->timer);}static void tx_timeout(struct device *dev){   struct netdev_private *np = (struct netdev_private *)dev->priv;   long ioaddr = dev->base_addr;   printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"" resetting...\n", dev->name, readl(ioaddr + ISR));#ifndef __alpha__   { int i; printk(KERN_DEBUG "  Rx ring %8.8x: ", (int)np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++)    printk(" %8.8x", (unsigned int)np->rx_ring.status); printk("\n"KERN_DEBUG"  Tx ring %8.8x: ", (int)np->tx_ring); for (i = 0; i < TX_RING_SIZE; i++)   printk(" %4.4x", np->tx_ring.status); printk("\n");   }#endif   /* Perhaps we should reinitialize the hardware here.  Just trigger a Tx demand for now. */   writel(0, dev->base_addr + TXPDR);   dev->if_port = 0;   /* Stop and restart the chip's Tx processes . */   dev->trans_start = jiffies;   np->stats.tx_errors++;   return;}/* Initialize the Rx and Tx rings, along with various 'dev' bits. */static void init_ring(struct device *dev){   struct netdev_private *np = (struct netdev_private *)dev->priv;   int i;   /* initialize rx variables */   np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);   np->cur_rx = &np->rx_ring[0];   np->lack_rxbuf = NULL;   np->really_rx_count = 0;   /* initial rx descriptors. */   for (i = 0; i < RX_RING_SIZE; i++)   { np->rx_ring.status = 0; np->rx_ring.control = np->rx_buf_sz<<RBSShift; np->rx_ring.next_desc = virt_to_bus(&np->rx_ring[i+1]); np->rx_ring.next_desc_logical = &np->rx_ring[i+1]; np->rx_ring.skbuff = NULL;   }   /* for the last rx descriptor */   np->rx_ring[i-1].next_desc = virt_to_bus(&np->rx_ring[0]);   np->rx_ring[i-1].next_desc_logical = &np->rx_ring[0];   /* allocate skb for rx buffers */   for (i = 0; i < RX_RING_SIZE; i++)   { struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz); if (skb == NULL) {    np->lack_rxbuf = &np->rx_ring;    break; } ++np->really_rx_count; np->rx_ring.skbuff = skb; skb->dev = dev;   /* Mark as being used by this device. */ np->rx_ring.buffer = virt_to_bus(skb->tail); np->rx_ring.status = RXOWN; np->rx_ring.control |= RXIC;   }   /* initialize tx variables */   np->cur_tx = &np->tx_ring[0];   np->cur_tx_copy = &np->tx_ring[0];   np->really_tx_count = 0;   np->free_tx_count = TX_RING_SIZE;   for (i = 0; i < TX_RING_SIZE; i++)   { np->tx_ring.status = 0; np->tx_ring.next_desc = virt_to_bus(&np->tx_ring[i+1]); np->tx_ring.next_desc_logical = &np->tx_ring[i+1]; np->tx_ring.skbuff = NULL;   }   /* for the last tx descriptor */   np->tx_ring[i-1].next_desc = virt_to_bus(&np->tx_ring[0]);   np->tx_ring[i-1].next_desc_logical = &np->tx_ring[0];   return;}static int start_tx(struct sk_buff *skb, struct device *dev){   struct netdev_private *np = (struct netdev_private *)dev->priv;   if (np->free_tx_count<=2)   { if (jiffies - dev->trans_start > TX_TIMEOUT)   tx_timeout(dev); return 1;   }   np->cur_tx_copy->skbuff = skb;   np->cur_tx_copy->buffer = virt_to_bus(skb->data);#define one_buffer#define BPT 1022#if defined(one_buffer)   np->cur_tx_copy->control = TXIC|TXLD|TXFD|CRCEnable|PADEnable;   np->cur_tx_copy->control |= (skb->len<<PKTSShift);   /* pkt size */   np->cur_tx_copy->control |= (skb->len<<TBSShift);    /* buffer size */   np->cur_tx_copy->status = TXOWN;   np->cur_tx_copy = np->cur_tx_copy->next_desc_logical;   --np->free_tx_count;#elif defined(two_buffer)   if (skb->len > BPT)   { struct fealnx_desc *next; /* for the first descriptor */ np->cur_tx_copy->control = TXIC|TXFD|CRCEnable|PADEnable; np->cur_tx_copy->control |= (skb->len<<PKTSShift);   /* pkt size */ np->cur_tx_copy->control |= (BPT<<TBSShift);    /* buffer size */ /* for the last descriptor */ next = (struct fealnx *)np->cur_tx_copy.next_desc_logical; next->skbuff = skb; next->control = TXIC|TXLD|CRCEnable|PADEnable; next->control |= (skb->len<<PKTSShift);/* pkt size */ next->control |= ((skb->len-BPT)<<TBSShift);/* buf size */ next->buffer = virt_to_bus(skb->data) + BPT; next->status = TXOWN; np->cur_tx_copy->status = TXOWN; np->cur_tx_copy = next->next_desc_logical; np->free_tx_count-=2;   }   else   { np->cur_tx_copy->control = TXIC|TXLD|TXFD|CRCEnable|PADEnable; np->cur_tx_copy->control |= (skb->len<<PKTSShift);   /* pkt size */ np->cur_tx_copy->control |= (skb->len<<TBSShift);    /* buffer size */ np->cur_tx_copy->status = TXOWN; np->cur_tx_copy = np->cur_tx_copy->next_desc_logical; --np->free_tx_count;   }#endif    ++np->really_tx_count;    writel(0, dev->base_addr + TXPDR);    dev->trans_start = jiffies;    return 0;}void free_one_rx_descriptor(struct netdev_private *np){   if (np->really_rx_count==RX_RING_SIZE)np->cur_rx->status = RXOWN;   else   { np->lack_rxbuf->skbuff = np->cur_rx->skbuff; np->lack_rxbuf->buffer = np->cur_rx->buffer; np->lack_rxbuf->status = RXOWN; ++np->really_rx_count; np->lack_rxbuf = np->lack_rxbuf->next_desc_logical;   }   np->cur_rx = np->cur_rx->next_desc_logical;}void reset_rx_descriptors(struct device *dev){   struct netdev_private *np = (struct netdev_private *)dev->priv;   stop_nic_rx(dev->base_addr, np->crvalue);   while (!(np->cur_rx->status&RXOWN))free_one_rx_descriptor(np);   allocate_rx_buffers(dev);   writel(virt_to_bus(np->cur_rx), dev->base_addr + RXLBA);   writel(np->crvalue, dev->base_addr + TCRRCR);}/* The interrupt handler does all of the Rx thread work and cleans up   after the Tx thread. */static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs){   struct device *dev = (struct device *)dev_instance;   struct netdev_private *np;   long ioaddr, boguscnt = max_interrupt_work;   writel(0, dev->base_addr + IMR);#ifndef final_version    /* Can never occur. */   if (dev == NULL)   { printk (KERN_ERR "Netdev interrupt handler(): IRQ %d for unknown "    "device.\n", irq); writel(FBE|TUNF|CNTOVF|RBU|TI|RI, dev->base_addr + IMR); return;   }#endif   ioaddr = dev->base_addr;   np = (struct netdev_private *)dev->priv;#if defined(__i386__)   /* A lock to prevent simultaneous entry bug on Intel SMP machines. */   if (test_and_set_bit(0, (void*)&dev->interrupt))   { printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",   dev->name); dev->interrupt = 0;/* Avoid halting machine. */ writel(FBE|TUNF|CNTOVF|RBU|TI|RI, ioaddr + IMR); return;   }#else   if (dev->interrupt)   { printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); writel(FBE|TUNF|CNTOVF|RBU|TI|RI, ioaddr + IMR); return;   }   dev->interrupt = 1;#endif   do   { u32 intr_status = readl(ioaddr + ISR); /* Acknowledge all of the current interrupt sources ASAP. */ writel(intr_status, ioaddr + ISR); if (debug)   printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n", dev->name,intr_status); if ((intr_status & (TUNF|CNTOVF|FBE|RBU|TI|RI)) == 0)   break; if (intr_status & FBE) {   /* fatal error */stop_nic_tx(ioaddr, 0);stop_nic_rx(ioaddr, 0);break; }; if (intr_status & TUNF)   writel(0, ioaddr + TXPDR); if (intr_status & CNTOVF) {    /* missed pkts */    np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;    /* crc error */    np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16; } if (intr_status & (RI | RBU)) {    if (intr_status & RI) netdev_rx(dev);    else reset_rx_descriptors(dev); } while (np->really_tx_count) {    long tx_status = np->cur_tx->status;    long tx_control = np->cur_tx->control;    if (!(tx_control & TXLD))    {  /* this pkt is combined by two tx descriptors */  struct fealnx_desc *next;  next = np->cur_tx->next_desc_logical;  tx_status = next->status;  tx_control = next->control;    }    if (tx_status & TXOWN) break;    if (tx_status &(CSL|LC|EC|UDF|HF))    {  np->stats.tx_errors++;  if (tx_status & EC)    np->stats.tx_aborted_errors++;  if (tx_status & CSL)    np->stats.tx_carrier_errors++;  if (tx_status & LC)    np->stats.tx_window_errors++;  if (tx_status & UDF)    np->stats.tx_fifo_errors++;  if ((tx_status & HF) && np->full_duplex == 0)    np->stats.tx_heartbeat_errors++;#ifdef ETHER_STATS  if (tx_status & EC)    np->stats.collisions16++;#endif    }    else    {#ifdef ETHER_STATS  if (tx_status & DFR)    np->stats.tx_deferred++;#endif#if LINUX_VERSION_CODE > 0x20127  np->stats.tx_bytes +=    ((tx_control & PKTSMask) >> PKTSShift);#endif  np->stats.collisions += ((tx_status & NCRMask)>>NCRShift);  np->stats.tx_packets++;    }    /* Free the original skb. */    dev_free_skb(np->cur_tx->skbuff);    np->cur_tx->skbuff = NULL;    --np->really_tx_count;    if (np->cur_tx->control&TXLD)    {  np->cur_tx = np->cur_tx->next_desc_logical;  ++np->free_tx_count;    }    else    {  np->cur_tx = np->cur_tx->next_desc_logical;  np->cur_tx = np->cur_tx->next_desc_logical;  np->free_tx_count+=2;    } }  /* end of for loop */ if (np->free_tx_count>=2)   mark_bh(NET_BH); if (--boguscnt < 0) {    printk(KERN_WARNING "%s: Too much work at interrupt, " "status=0x%4.4x.\n", dev->name, intr_status);    break; }   } while (1);   /* read the tally counters */   /* missed pkts */   np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;   /* crc error */   np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;   if (debug)printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",  dev->name, readl(ioaddr + ISR));#if defined(__i386__)   clear_bit(0, (void*)&dev->interrupt);#else   dev->interrupt = 0;#endif   writel(FBE|TUNF|CNTOVF|RBU|TI|RI, ioaddr + IMR);   return;}/* This routine is logically part of the interrupt handler, but seperated   for clarity and better register allocation. */static int netdev_rx(struct device *dev){   struct netdev_private *np = (struct netdev_private *)dev->priv;   /* If EOP is set on the next entry, it's a new packet. Send it up. */   while (!(np->cur_rx->status & RXOWN))   { s32 rx_status = np->cur_rx->status; if (np->really_rx_count==0)   break; if (debug)   printk(KERN_DEBUG "  netdev_rx() status was %8.8x.\n", rx_status); if ((!((rx_status&RXFSD)&&(rx_status&RXLSD))) || (rx_status&ErrorSummary)) {    if (rx_status & ErrorSummary)    {  /* there was a fatal error */  if (debug)    printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", dev->name, rx_status);  np->stats.rx_errors++; /* end of a packet.*/  if (rx_status & (LONG|RUNT))    np->stats.rx_length_errors++;  if (rx_status & RXER)    np->stats.rx_frame_errors++;  if (rx_status & CRC)    np->stats.rx_crc_errors++;    }    else    {  int need_to_reset=0;  int desno=0;  if (rx_status & RXFSD)  {  /* this pkt is too long, over one rx buffer */struct fealnx_desc *cur;/* check this packet is received completely? */cur = np->cur_rx;while (desno<=np->really_rx_count){   ++desno;   if ((!(cur->status&RXOWN)) && (cur->status&RXLSD))break;   /* goto next rx descriptor */   cur = cur->next_desc_logical;}if (desno>np->really_rx_count)  need_to_reset = 1;  }  else /* RXLSD did not find, something error */    need_to_reset = 1;  if (need_to_reset==0)  {int i;np->stats.rx_length_errors++;/* free all rx descriptors related this long pkt */for (i=0;i<desno;++i)  free_one_rx_descriptor(np);continue;  }  else  {  /* something error, need to reset this chip */reset_rx_descriptors(dev);  }  break; /* exit the while loop */    } } else /* this received pkt is ok */ {    struct sk_buff *skb;    /* Omit the four octet CRC from the length. */    short pkt_len = ((rx_status&FLNGMASK)>>FLNGShift) -4;#ifndef final_version    if (debug) printk(KERN_DEBUG "  netdev_rx() normal Rx pkt length %d"   " status %x.\n", pkt_len, rx_status);#endif    /* Check if the packet is long enough to accept without copying  to a minimally-sized skbuff. */    if (pkt_len < rx_copybreak &&   (skb = dev_alloc_skb(pkt_len + 2)) != NULL)    {  skb->dev = dev;  skb_reserve(skb, 2);    /* 16 byte align the IP header */ /* Call copy + cksum if available. */#if ! defined(__alpha__)  eth_copy_and_sum(skb, bus_to_virt(np->cur_rx->buffer), pkt_len, 0);  skb_put(skb, pkt_len);#else  memcpy(skb_put(skb, pkt_len), bus_to_virt(np->cur_rx->buffer),    pkt_len);#endif    }    else    {  skb_put(skb = np->cur_rx->skbuff, pkt_len);  np->cur_rx->skbuff = NULL;  if (np->really_rx_count == RX_RING_SIZE)    np->lack_rxbuf = np->cur_rx;  --np->really_rx_count;    }    skb->protocol = eth_type_trans(skb, dev);    netif_rx(skb);    dev->last_rx = jiffies;    np->stats.rx_packets++;#if LINUX_VERSION_CODE > 0x20127    np->stats.rx_bytes += pkt_len;#endif } if (np->cur_rx->skbuff==NULL) {    struct sk_buff *skb;    skb = dev_alloc_skb(np->rx_buf_sz);    if (skb !=NULL)    {  skb->dev = dev;   /* Mark as being used by this device. */  np->cur_rx->buffer = virt_to_bus(skb->tail);  np->cur_rx->skbuff = skb;  ++np->really_rx_count;    } } if (np->cur_rx->skbuff!=NULL)   free_one_rx_descriptor(np);   }  /* end of while loop */   /*  allocate skb for rx buffers */   allocate_rx_buffers(dev);   return 0;}static struct enet_statistics *get_stats(struct device *dev){   long ioaddr = dev->base_addr;   struct netdev_private *np = (struct netdev_private *)dev->priv;   /* The chip only need report frame silently dropped. */   if (dev->start)   { np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff; np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;   }   return &np->stats;}static unsigned const ethernet_polynomial = 0x04c11db7U;static inline u32 ether_crc(int length, unsigned char *data){   int crc = -1;   while(--length >= 0)   { unsigned char current_octet = *data++; int bit; for (bit = 0; bit < 8; bit++, current_octet >>= 1) {    crc = (crc << 1) ^((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); }   }   return crc;}static void set_rx_mode(struct device *dev){   struct netdev_private *np = (struct netdev_private *)dev->priv;   long ioaddr = dev->base_addr;   u32 mc_filter[2];   /* Multicast hash filter */   u32 rx_mode;   if (dev->flags & IFF_PROMISC)   {  /* Set promiscuous. */ /* Unconditionally log net taps. */ printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name); memset(mc_filter, 0xff, sizeof(mc_filter)); rx_mode = PROM|AB|AM;   }   elseif ((dev->mc_count > multicast_filter_limit)    ||  (dev->flags & IFF_ALLMULTI)){   /* Too many to match, or accept all multicasts. */   memset(mc_filter, 0xff, sizeof(mc_filter));   rx_mode = AB|AM;}else{   struct dev_mc_list *mclist;   int i;   memset(mc_filter, 0, sizeof(mc_filter));   for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;   i++, mclist = mclist->next)   { set_bit((ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F,mc_filter);   }   rx_mode = AB|AM;}   stop_nic_tx(ioaddr, np->crvalue);   stop_nic_rx(ioaddr, np->crvalue&(~0x40000));   writel(mc_filter[0], ioaddr + MAR0);   writel(mc_filter[1], ioaddr + MAR1);   np->crvalue &= ~RxModeMask;   np->crvalue |= rx_mode;   writel(np->crvalue, ioaddr + TCRRCR);}static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd){   u16 *data = (u16 *)&rq->ifr_data;   switch(cmd)   { case SIOCDEVPRIVATE:  /* Get the address of the PHY in use. */   data[0] = ((struct netdev_private *)dev->priv)->phys[0] & 0x1f;   /* Fall Through */ case SIOCDEVPRIVATE+1:/* Read the specified MII register. */   data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);   return 0; case SIOCDEVPRIVATE+2:/* Write the specified MII register */   if (!suser())return -EPERM;   mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);   return 0; default:   return -EOPNOTSUPP;   }}static int netdev_close(struct device *dev){   long ioaddr = dev->base_addr;   struct netdev_private *np = (struct netdev_private *)dev->priv;   int i;   dev->start = 0;   dev->tbusy = 1;   /* Disable interrupts by clearing the interrupt mask. */   writel(0x0000, ioaddr + IMR);   /* Stop the chip's Tx and Rx processes. */   stop_nic_tx(ioaddr, 0);   stop_nic_rx(ioaddr, 0);   del_timer(&np->timer);#ifdef __i386__   if (debug)   { printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n",   (int)virt_to_bus(np->tx_ring)); for (i = 0; i < TX_RING_SIZE; i++)    printk(" #%d desc. %4.4x %4.4x %8.8x.\n", i, np->tx_ring.control, np->tx_ring.status, np->tx_ring.buffer); printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n",   (int)virt_to_bus(np->rx_ring)); for (i = 0; i < RX_RING_SIZE; i++) {    printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n", i, np->rx_ring.control, np->rx_ring.status, np->rx_ring.buffer); }   }#endif /* __i386__ debugging only */   free_irq(dev->irq, dev);   /* Free all the skbuffs in the Rx queue. */   for (i = 0; i < RX_RING_SIZE; i++)   { np->rx_ring.status = 0; if (np->rx_ring.skbuff) {#if LINUX_VERSION_CODE < 0x20100    np->rx_ring.skbuff->free = 1;#endif    dev_free_skb(np->rx_ring.skbuff); } np->rx_ring.skbuff = NULL;   }   for (i = 0; i < TX_RING_SIZE; i++)   { if (np->tx_ring.skbuff)   dev_free_skb(np->tx_ring.skbuff); np->tx_ring.skbuff = NULL;   }   MOD_DEC_USE_COUNT;   return 0;}#ifdef MODULEint init_module(void){   if (debug) /* Emit version even if no cards detected. */printk(KERN_INFO "%s" KERN_INFO "%s", version, version1);#ifdef CARDBUS   register_driver(&etherdev_ops);   return 0;#else   return pci_etherdev_probe(NULL, pci_tbl);#endif}void cleanup_module(void){   struct device *next_dev;#ifdef CARDBUS   unregister_driver(&etherdev_ops);#endif   /* No need to check MOD_IN_USE, as sys_delete_module() checks. */   while (root_net_dev)   { next_dev = ((struct netdev_private *)root_net_dev->priv)->next_module; unregister_netdev(root_net_dev);#ifdef USE_IO release_region(root_net_dev->base_addr, pci_tbl[0].io_size);#else iounmap((char *)(root_net_dev->base_addr));#endif kfree(root_net_dev); root_net_dev = next_dev;   }}#elseint fealnx_probe(struct device *dev){   printk(KERN_INFO "%s" KERN_INFO "%s", version, version1);   return pci_etherdev_probe(dev, pci_tbl);}#endif  /* MODULE *//* * Local variables: *  compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c fealnx.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c fealnx.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" *  c-indent-level: 4 *  c-basic-offset: 4 *  tab-width: 4 * End: */but i got no way to compile (no compiler downloaded, and my conniction is too slow)   
/* Keep the ring sizes a power of two for compile efficiency. *//* The compiler will convert <unsigned>'%'<2^N> into a bit mask.   *//* Making the Tx ring too large decreases the effectiveness of channel  *//* bonding and packet priority. *//* There are no ill effects from too-large receive rings.*/// 88-12-9 modify,// #define TX_RING_SIZE    16// #define RX_RING_SIZE    32#define TX_RING_SIZE    6#define RX_RING_SIZE    12Haha! That driver is 20 years old!You should spend the time getting a compiler on your system, if you want to compile your own drivers. I guess you could make an online linux account somewhere  (?) and compile it.