fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / net / cs89x0.c
index b04bf5e..4612f71 100644 (file)
   Changelog:
 
   Mike Cruse        : mcruse@cti-ltd.com
-                    : Changes for Linux 2.0 compatibility. 
+                    : Changes for Linux 2.0 compatibility.
                     : Added dev_id parameter in net_interrupt(),
                     : request_irq() and free_irq(). Just NULL for now.
 
   Mike Cruse        : Added MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT macros
                     : in net_open() and net_close() so kerneld would know
-                    : that the module is in use and wouldn't eject the 
+                    : that the module is in use and wouldn't eject the
                     : driver prematurely.
 
   Mike Cruse        : Rewrote init_module() and cleanup_module using 8390.c
@@ -31,7 +31,7 @@
 
   Russ Nelson       : Jul 13 1998.  Added RxOnly DMA support.
 
-  Melody Lee        : Aug 10 1999.  Changes for Linux 2.2.5 compatibility. 
+  Melody Lee        : Aug 10 1999.  Changes for Linux 2.2.5 compatibility.
                     : email: ethernet@crystal.cirrus.com
 
   Alan Cox          : Removed 1.2 support, added 2.1 extra counters.
   Oskar Schirmer    : oskar@scara.com
                     : HiCO.SH4 (superh) support added (irq#1, cs89x0_media=)
 
+  Deepak Saxena     : dsaxena@plexity.net
+                    : Intel IXDP2x01 (XScale ixp2x00 NPU) platform support
+
+  Dmitry Pervushin  : dpervushin@ru.mvista.com
+                    : PNX010X platform support
+
+  Deepak Saxena     : dsaxena@plexity.net
+                    : Intel IXDP2351 platform support
+
+  Dmitry Pervushin  : dpervushin@ru.mvista.com
+                    : PNX010X platform support
+
 */
 
 /* Always include 'config.h' first in case the user wants to turn on
    or override something. */
-#include <linux/config.h>
 #include <linux/module.h>
 
 /*
  * Note that even if DMA is turned off we still support the 'dma' and  'use_dma'
  * module options so we don't break any startup scripts.
  */
+#ifndef CONFIG_ISA_DMA_API
+#define ALLOW_DMA      0
+#else
 #define ALLOW_DMA      1
+#endif
 
 /*
  * Set this to zero to remove all the debug statements via
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
 
 #include <asm/system.h>
-#include <asm/bitops.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #if ALLOW_DMA
 #include <asm/dma.h>
 #endif
@@ -146,12 +163,12 @@ static char version[] __initdata =
 /* First, a few definitions that the brave might change.
    A zero-terminated list of I/O addresses to be probed. Some special flags..
       Addr & 1 = Read back the address port, look for signature and reset
-                 the page window before probing 
-      Addr & 3 = Reset the page window and probe 
+                 the page window before probing
+      Addr & 3 = Reset the page window and probe
    The CLPS eval board has the Cirrus chip at 0x80090300, in ARM IO space,
    but it is possible that a Cirrus board could be plugged into the ISA
    slots. */
-/* The cs8900 has 4 IRQ pins, software selectable. cs8900_irq_map maps 
+/* The cs8900 has 4 IRQ pins, software selectable. cs8900_irq_map maps
    them to system IRQ numbers. This mapping is card specific and is set to
    the configuration of the Cirrus Eval board for this chip. */
 #ifdef CONFIG_ARCH_CLPS7500
@@ -162,6 +179,21 @@ static unsigned int cs8900_irq_map[] = {12,0,0,0};
 static unsigned int netcard_portlist[] __initdata =
    { 0x0300, 0};
 static unsigned int cs8900_irq_map[] = {1,0,0,0};
+#elif defined(CONFIG_MACH_IXDP2351)
+static unsigned int netcard_portlist[] __initdata = {IXDP2351_VIRT_CS8900_BASE, 0};
+static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0};
+#include <asm/irq.h>
+#elif defined(CONFIG_ARCH_IXDP2X01)
+#include <asm/irq.h>
+static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
+static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
+#elif defined(CONFIG_ARCH_PNX010X)
+#include <asm/irq.h>
+#include <asm/arch/gpio.h>
+#define CIRRUS_DEFAULT_BASE    IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x200000)      /* = Physical address 0x48200000 */
+#define CIRRUS_DEFAULT_IRQ     VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */
+static unsigned int netcard_portlist[] __initdata = {CIRRUS_DEFAULT_BASE, 0};
+static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0};
 #else
 static unsigned int netcard_portlist[] __initdata =
    { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
@@ -217,7 +249,7 @@ struct net_local {
 static int cs89x0_probe1(struct net_device *dev, int ioaddr, int modular);
 static int net_open(struct net_device *dev);
 static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t net_interrupt(int irq, void *dev_id);
 static void set_multicast_list(struct net_device *dev);
 static void net_timeout(struct net_device *dev);
 static void net_rx(struct net_device *dev);
@@ -228,6 +260,9 @@ static int get_eeprom_data(struct net_device *dev, int off, int len, int *buffer
 static int get_eeprom_cksum(int off, int len, int *buffer);
 static int set_mac_address(struct net_device *dev, void *addr);
 static void count_rx_errors(int status, struct net_local *lp);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void net_poll_controller(struct net_device *dev);
+#endif
 #if ALLOW_DMA
 static void get_dma_channel(struct net_device *dev);
 static void release_dma_buff(struct net_local *lp);
@@ -264,7 +299,7 @@ static int __init media_fn(char *str)
 
 __setup("cs89x0_media=", media_fn);
 
-\f
+
 /* Check for a network adaptor of this type, and return '0' iff one exists.
    If dev->base_addr == 0, probe all likely locations.
    If dev->base_addr == 1, always return failure.
@@ -307,13 +342,7 @@ struct net_device * __init cs89x0_probe(int unit)
        }
        if (err)
                goto out;
-       err = register_netdev(dev);
-       if (err)
-               goto out1;
        return dev;
-out1:
-       outw(PP_ChipID, dev->base_addr + ADD_PORT);
-       release_region(dev->base_addr, NETCARD_IO_EXTENT);
 out:
        free_netdev(dev);
        printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected.  Be sure to disable PnP with SETUP\n");
@@ -321,30 +350,96 @@ out:
 }
 #endif
 
-static int
-readreg(struct net_device *dev, int portno)
+#if defined(CONFIG_MACH_IXDP2351)
+static u16
+readword(unsigned long base_addr, int portno)
 {
-       outw(portno, dev->base_addr + ADD_PORT);
-       return inw(dev->base_addr + DATA_PORT);
+       return __raw_readw(base_addr + (portno << 1));
 }
 
 static void
-writereg(struct net_device *dev, int portno, int value)
+writeword(unsigned long base_addr, int portno, u16 value)
 {
-       outw(portno, dev->base_addr + ADD_PORT);
-       outw(value, dev->base_addr + DATA_PORT);
+       __raw_writew(value, base_addr + (portno << 1));
+}
+#elif defined(CONFIG_ARCH_IXDP2X01)
+static u16
+readword(unsigned long base_addr, int portno)
+{
+       return __raw_readl(base_addr + (portno << 1));
 }
 
-static int
-readword(struct net_device *dev, int portno)
+static void
+writeword(unsigned long base_addr, int portno, u16 value)
+{
+       __raw_writel(value, base_addr + (portno << 1));
+}
+#elif defined(CONFIG_ARCH_PNX010X)
+static u16
+readword(unsigned long base_addr, int portno)
 {
-       return inw(dev->base_addr + portno);
+       return inw(base_addr + (portno << 1));
 }
 
 static void
-writeword(struct net_device *dev, int portno, int value)
+writeword(unsigned long base_addr, int portno, u16 value)
 {
-       outw(value, dev->base_addr + portno);
+       outw(value, base_addr + (portno << 1));
+}
+#else
+static u16
+readword(unsigned long base_addr, int portno)
+{
+       return inw(base_addr + portno);
+}
+
+static void
+writeword(unsigned long base_addr, int portno, u16 value)
+{
+       outw(value, base_addr + portno);
+}
+#endif
+
+static void
+readwords(unsigned long base_addr, int portno, void *buf, int length)
+{
+       u8 *buf8 = (u8 *)buf;
+
+       do {
+               u16 tmp16;
+
+               tmp16 = readword(base_addr, portno);
+               *buf8++ = (u8)tmp16;
+               *buf8++ = (u8)(tmp16 >> 8);
+       } while (--length);
+}
+
+static void
+writewords(unsigned long base_addr, int portno, void *buf, int length)
+{
+       u8 *buf8 = (u8 *)buf;
+
+       do {
+               u16 tmp16;
+
+               tmp16 = *buf8++;
+               tmp16 |= (*buf8++) << 8;
+               writeword(base_addr, portno, tmp16);
+       } while (--length);
+}
+
+static u16
+readreg(struct net_device *dev, u16 regno)
+{
+       writeword(dev->base_addr, ADD_PORT, regno);
+       return readword(dev->base_addr, DATA_PORT);
+}
+
+static void
+writereg(struct net_device *dev, u16 regno, u16 value)
+{
+       writeword(dev->base_addr, ADD_PORT, regno);
+       writeword(dev->base_addr, DATA_PORT, value);
 }
 
 static int __init
@@ -392,6 +487,19 @@ get_eeprom_cksum(int off, int len, int *buffer)
        return -1;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void net_poll_controller(struct net_device *dev)
+{
+       disable_irq(dev->irq);
+       net_interrupt(dev->irq, dev);
+       enable_irq(dev->irq);
+}
+#endif
+
 /* This is the real probe routine.  Linux has a history of friendly device
    probes on the ISA bus.  A good device probes avoids doing writes, and
    verifies that the correct device exists and functions.
@@ -404,6 +512,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
        struct net_local *lp = netdev_priv(dev);
        static unsigned version_printed;
        int i;
+       int tmp;
        unsigned rev_type = 0;
        int eeprom_buff[CHKSUM_LEN];
        int retval;
@@ -425,6 +534,30 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
 #endif
         }
 
+#ifdef CONFIG_ARCH_PNX010X
+       initialize_ebi();
+
+       /* Map GPIO registers for the pins connected to the CS8900a. */
+       if (map_cirrus_gpio() < 0)
+               return -ENODEV;
+
+       reset_cirrus();
+
+       /* Map event-router registers. */
+       if (map_event_router() < 0)
+               return -ENODEV;
+
+       enable_cirrus_irq();
+
+       unmap_cirrus_gpio();
+       unmap_event_router();
+
+       dev->base_addr = ioaddr;
+
+       for (i = 0 ; i < 3 ; i++)
+               readreg(dev, 0);
+#endif
+
        /* Grab the region so we can find another board if autoIRQ fails. */
        /* WTF is going on here? */
        if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) {
@@ -436,8 +569,8 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
 
 #ifdef CONFIG_SH_HICOSH4
        /* truely reset the chip */
-       outw(0x0114, ioaddr + ADD_PORT);
-       outw(0x0040, ioaddr + DATA_PORT);
+       writeword(ioaddr, ADD_PORT, 0x0114);
+       writeword(ioaddr, DATA_PORT, 0x0040);
 #endif
 
        /* if they give us an odd I/O address, then do ONE write to
@@ -448,20 +581,24 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
                if (net_debug > 1)
                        printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr);
                if ((ioaddr & 2) != 2)
-                       if ((inw((ioaddr & ~3)+ ADD_PORT) & ADD_MASK) != ADD_SIG) {
+                       if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) {
                                printk(KERN_ERR "%s: bad signature 0x%x\n",
-                                       dev->name, inw((ioaddr & ~3)+ ADD_PORT));
+                                       dev->name, readword(ioaddr & ~3, ADD_PORT));
                                retval = -ENODEV;
                                goto out2;
                        }
-               ioaddr &= ~3;
-               outw(PP_ChipID, ioaddr + ADD_PORT);
        }
-printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
 
-       if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) {
-               printk(KERN_ERR "%s: incorrect signature 0x%x\n",
-                       dev->name, inw(ioaddr + DATA_PORT));
+       ioaddr &= ~3;
+       printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n",
+                       ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT));
+       writeword(ioaddr, ADD_PORT, PP_ChipID);
+
+       tmp = readword(ioaddr, DATA_PORT);
+       if (tmp != CHIP_EISA_ID_SIG) {
+               printk(KERN_DEBUG "%s: incorrect signature at %x[%x]: 0x%x!="
+                       CHIP_EISA_ID_SIG_STR "\n",
+                       dev->name, ioaddr, DATA_PORT, tmp);
                retval = -ENODEV;
                goto out2;
        }
@@ -493,7 +630,7 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
               dev->base_addr);
 
        reset_chip(dev);
-   
+
         /* Here we read the current configuration of the chip. If there
           is no Extended EEPROM then the idea is to not disturb the chip
           configuration, it should have been correctly setup by automatic
@@ -517,7 +654,7 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
                cnt = (*confd++ & 0x00ff) >> 1;
                while (--cnt > 0) {
                        __u16 j = *confd++;
-                       
+
                        switch (j & 0x0fff) {
                        case PP_IA:
                                for (i = 0; i < ETH_ALEN/2; i++) {
@@ -533,7 +670,7 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
        } else
 #endif
 
-        if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) == 
+        if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) ==
              (EEPROM_OK|EEPROM_PRESENT)) {
                /* Load the MAC. */
                for (i=0; i < ETH_ALEN/2; i++) {
@@ -542,17 +679,17 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
                        dev->dev_addr[i*2] = Addr & 0xFF;
                        dev->dev_addr[i*2+1] = Addr >> 8;
                }
-   
-               /* Load the Adapter Configuration. 
-                  Note:  Barring any more specific information from some 
-                  other source (ie EEPROM+Schematics), we would not know 
-                  how to operate a 10Base2 interface on the AUI port. 
-                  However, since we  do read the status of HCB1 and use 
-                  settings that always result in calls to control_dc_dc(dev,0) 
-                  a BNC interface should work if the enable pin 
-                  (dc/dc converter) is on HCB1. It will be called AUI 
+
+               /* Load the Adapter Configuration.
+                  Note:  Barring any more specific information from some
+                  other source (ie EEPROM+Schematics), we would not know
+                  how to operate a 10Base2 interface on the AUI port.
+                  However, since we  do read the status of HCB1 and use
+                  settings that always result in calls to control_dc_dc(dev,0)
+                  a BNC interface should work if the enable pin
+                  (dc/dc converter) is on HCB1. It will be called AUI
                   however. */
-          
+
                lp->adapter_cnf = 0;
                i = readreg(dev, PP_LineCTL);
                /* Preserve the setting of the HCB1 pin. */
@@ -569,22 +706,22 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
                        lp->adapter_cnf |=  A_CNF_AUI | A_CNF_MEDIA_AUI;
                /* Check if the card is in Auto mode. */
                if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUTO_AUI_10BASET)
-                       lp->adapter_cnf |=  A_CNF_AUI | A_CNF_10B_T | 
+                       lp->adapter_cnf |=  A_CNF_AUI | A_CNF_10B_T |
                        A_CNF_MEDIA_AUI | A_CNF_MEDIA_10B_T | A_CNF_MEDIA_AUTO;
-               
+
                if (net_debug > 1)
                        printk(KERN_INFO "%s: PP_LineCTL=0x%x, adapter_cnf=0x%x\n",
                                        dev->name, i, lp->adapter_cnf);
 
                /* IRQ. Other chips already probe, see below. */
-               if (lp->chip_type == CS8900) 
+               if (lp->chip_type == CS8900)
                        lp->isa_config = readreg(dev, PP_CS8900_ISAINT) & INT_NO_MASK;
-          
+
                printk( "[Cirrus EEPROM] ");
        }
 
         printk("\n");
-   
+
        /* First check to see if an EEPROM is attached. */
 #ifdef CONFIG_SH_HICOSH4 /* no EEPROM on HiCO, don't hazzle with it here */
        if (1) {
@@ -599,13 +736,13 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
                /* Check if the chip was able to read its own configuration starting
                   at 0 in the EEPROM*/
                if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) !=
-                   (EEPROM_OK|EEPROM_PRESENT)) 
+                   (EEPROM_OK|EEPROM_PRESENT))
                        printk(KERN_WARNING "cs89x0: Extended EEPROM checksum bad and no Cirrus EEPROM, relying on command line\n");
-                  
+
         } else {
                /* This reads an extended EEPROM that is not documented
                   in the CS8900 datasheet. */
-               
+
                 /* get transmission control word  but keep the autonegotiation bits */
                 if (!lp->auto_neg_cnf) lp->auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET/2];
                 /* Store adapter configuration */
@@ -665,12 +802,15 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
        } else {
                i = lp->isa_config & INT_NO_MASK;
                if (lp->chip_type == CS8900) {
+#if defined(CONFIG_MACH_IXDP2351) || defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X)
+                       i = cs8900_irq_map[0];
+#else
                        /* Translate the IRQ using the IRQ mapping table. */
                        if (i >= sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0]))
                                printk("\ncs89x0: invalid ISA interrupt number %d\n", i);
                        else
                                i = cs8900_irq_map[i];
-                       
+
                        lp->irq_map = CS8900_IRQ_MAP; /* fixed IRQ map for CS8900 */
                } else {
                        int irq_map_buff[IRQ_MAP_LEN/2];
@@ -681,6 +821,7 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
                                if ((irq_map_buff[0] & 0xff) == PNP_IRQ_FRMT)
                                        lp->irq_map = (irq_map_buff[0]>>8) | (irq_map_buff[1] << 8);
                        }
+#endif
                }
                if (!dev->irq)
                        dev->irq = i;
@@ -714,18 +855,27 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
        dev->get_stats          = net_get_stats;
        dev->set_multicast_list = set_multicast_list;
        dev->set_mac_address    = set_mac_address;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       dev->poll_controller    = net_poll_controller;
+#endif
 
        printk("\n");
        if (net_debug)
                printk("cs89x0_probe1() successful\n");
+
+       retval = register_netdev(dev);
+       if (retval)
+               goto out3;
        return 0;
+out3:
+       writeword(dev->base_addr, ADD_PORT, PP_ChipID);
 out2:
        release_region(ioaddr & ~3, NETCARD_IO_EXTENT);
 out1:
        return retval;
 }
 
-\f
+
 /*********************************
  * This page contains DMA routines
 **********************************/
@@ -884,40 +1034,44 @@ skip_this_frame:
 
 void  __init reset_chip(struct net_device *dev)
 {
+#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
        struct net_local *lp = netdev_priv(dev);
        int ioaddr = dev->base_addr;
+#endif
        int reset_start_time;
 
        writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
 
        /* wait 30 ms */
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(30*HZ/1000);
+       msleep(30);
 
+#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
        if (lp->chip_type != CS8900) {
                /* Hardware problem requires PNP registers to be reconfigured after a reset */
-               outw(PP_CS8920_ISAINT, ioaddr + ADD_PORT);
+               writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT);
                outb(dev->irq, ioaddr + DATA_PORT);
                outb(0,      ioaddr + DATA_PORT + 1);
 
-               outw(PP_CS8920_ISAMemB, ioaddr + ADD_PORT);
+               writeword(ioaddr, ADD_PORT, PP_CS8920_ISAMemB);
                outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT);
                outb((dev->mem_start >> 8) & 0xff,   ioaddr + DATA_PORT + 1);
        }
+#endif /* IXDP2x01 */
+
        /* Wait until the chip is reset */
        reset_start_time = jiffies;
        while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2)
                ;
 }
 
-\f
+
 static void
 control_dc_dc(struct net_device *dev, int on_not_off)
 {
        struct net_local *lp = netdev_priv(dev);
        unsigned int selfcontrol;
        int timenow = jiffies;
-       /* control the DC to DC convertor in the SelfControl register.  
+       /* control the DC to DC convertor in the SelfControl register.
           Note: This is hooked up to a general purpose pin, might not
           always be a DC to DC convertor. */
 
@@ -1028,8 +1182,8 @@ send_test_pkt(struct net_device *dev)
        memcpy(test_packet,          dev->dev_addr, ETH_ALEN);
        memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN);
 
-        writeword(dev, TX_CMD_PORT, TX_AFTER_ALL);
-        writeword(dev, TX_LEN_PORT, ETH_ZLEN);
+        writeword(dev->base_addr, TX_CMD_PORT, TX_AFTER_ALL);
+        writeword(dev->base_addr, TX_LEN_PORT, ETH_ZLEN);
 
        /* Test to see if the chip has allocated memory for the packet */
        while (jiffies - timenow < 5)
@@ -1039,7 +1193,7 @@ send_test_pkt(struct net_device *dev)
                return 0;       /* this shouldn't happen */
 
        /* Write the contents of the packet */
-       outsw(dev->base_addr + TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1);
+       writewords(dev->base_addr, TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1);
 
        if (net_debug > 1) printk("Sending test packet ");
        /* wait a couple of jiffies for packet to be received */
@@ -1086,7 +1240,7 @@ detect_bnc(struct net_device *dev)
                return DETECTED_NONE;
 }
 
-\f
+
 static void
 write_irq(struct net_device *dev, int chip_type, int irq)
 {
@@ -1124,7 +1278,7 @@ net_open(struct net_device *dev)
        int i;
        int ret;
 
-#ifndef CONFIG_SH_HICOSH4 /* uses irq#1, so this won't work */
+#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX010X) /* uses irq#1, so this won't work */
        if (dev->irq < 2) {
                /* Allow interrupts to be generated by the chip */
 /* Cirrus' release had this: */
@@ -1155,12 +1309,14 @@ net_open(struct net_device *dev)
        else
 #endif
        {
+#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X)
                if (((1 << dev->irq) & lp->irq_map) == 0) {
                        printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
                                dev->name, dev->irq, lp->irq_map);
                        ret = -EAGAIN;
                        goto bad_out;
                }
+#endif
 /* FIXME: Cirrus' release had this: */
                writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
 /* And 2.3.47 had this: */
@@ -1238,6 +1394,9 @@ net_open(struct net_device *dev)
        case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break;
         default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
         }
+#ifdef CONFIG_ARCH_PNX010X
+       result = A_CNF_10B_T;
+#endif
         if (!result) {
                 printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name);
         release_irq:
@@ -1376,8 +1535,8 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
        netif_stop_queue(dev);
 
        /* initiate a transmit sequence */
-       writeword(dev, TX_CMD_PORT, lp->send_cmd);
-       writeword(dev, TX_LEN_PORT, skb->len);
+       writeword(dev->base_addr, TX_CMD_PORT, lp->send_cmd);
+       writeword(dev->base_addr, TX_LEN_PORT, skb->len);
 
        /* Test to see if the chip has allocated memory for the packet */
        if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
@@ -1385,14 +1544,15 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
                 * Gasp!  It hasn't.  But that shouldn't happen since
                 * we're waiting for TxOk, so return 1 and requeue this packet.
                 */
-               
+
                spin_unlock_irq(&lp->lock);
                if (net_debug) printk("cs89x0: Tx buffer not free!\n");
                return 1;
        }
        /* Write the contents of the packet */
-       outsw(dev->base_addr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
+       writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
        spin_unlock_irq(&lp->lock);
+       lp->stats.tx_bytes += skb->len;
        dev->trans_start = jiffies;
        dev_kfree_skb (skb);
 
@@ -1409,11 +1569,11 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
 
        return 0;
 }
-\f
+
 /* The typical workload of the driver:
    Handle the network interface interrupts. */
-   
-static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+
+static irqreturn_t net_interrupt(int irq, void *dev_id)
 {
        struct net_device *dev = dev_id;
        struct net_local *lp;
@@ -1430,7 +1590,7 @@ static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
            course, if you're on a slow machine, and packets are arriving
            faster than you can read them off, you're screwed.  Hasta la
            vista, baby!  */
-       while ((status = readword(dev, ISQ_PORT))) {
+       while ((status = readword(dev->base_addr, ISQ_PORT))) {
                if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);
                handled = 1;
                switch(status & ISQ_EVENT_MASK) {
@@ -1524,8 +1684,8 @@ net_rx(struct net_device *dev)
        int status, length;
 
        int ioaddr = dev->base_addr;
-       status = inw(ioaddr + RX_FRAME_PORT);
-       length = inw(ioaddr + RX_FRAME_PORT);
+       status = readword(ioaddr, RX_FRAME_PORT);
+       length = readword(ioaddr, RX_FRAME_PORT);
 
        if ((status & RX_OK) == 0) {
                count_rx_errors(status, lp);
@@ -1544,9 +1704,9 @@ net_rx(struct net_device *dev)
        skb_reserve(skb, 2);    /* longword align L3 header */
        skb->dev = dev;
 
-       insw(ioaddr + RX_FRAME_PORT, skb_put(skb, length), length >> 1);
+       readwords(ioaddr, RX_FRAME_PORT, skb_put(skb, length), length >> 1);
        if (length & 1)
-               skb->data[length-1] = inw(ioaddr + RX_FRAME_PORT);
+               skb->data[length-1] = readword(ioaddr, RX_FRAME_PORT);
 
        if (net_debug > 3) {
                printk( "%s: received %d byte packet of type %x\n",
@@ -1575,10 +1735,12 @@ static void release_dma_buff(struct net_local *lp)
 static int
 net_close(struct net_device *dev)
 {
+#if ALLOW_DMA
        struct net_local *lp = netdev_priv(dev);
+#endif
 
        netif_stop_queue(dev);
-       
+
        writereg(dev, PP_RxCFG, 0);
        writereg(dev, PP_TxCFG, 0);
        writereg(dev, PP_BufCFG, 0);
@@ -1629,7 +1791,7 @@ static void set_multicast_list(struct net_device *dev)
                /* The multicast-accept list is initialized to accept-all, and we
                   rely on higher-level filtering for now. */
                lp->rx_mode = RX_MULTCAST_ACCEPT;
-       } 
+       }
        else
                lp->rx_mode = 0;
 
@@ -1671,8 +1833,8 @@ static int set_mac_address(struct net_device *dev, void *p)
 static struct net_device *dev_cs89x0;
 
 /*
- * Support the 'debug' module parm even if we're compiled for non-debug to 
- * avoid breaking someone's startup scripts 
+ * Support the 'debug' module parm even if we're compiled for non-debug to
+ * avoid breaking someone's startup scripts
  */
 
 static int io;
@@ -1685,14 +1847,14 @@ static int use_dma;                     /* These generate unused var warnings if ALLOW_DMA = 0 */
 static int dma;
 static int dmasize=16;                 /* or 64 */
 
-MODULE_PARM(io, "i");
-MODULE_PARM(irq, "i");
-MODULE_PARM(debug, "i");
-MODULE_PARM(media, "c8");
-MODULE_PARM(duplex, "i");
-MODULE_PARM(dma , "i");
-MODULE_PARM(dmasize , "i");
-MODULE_PARM(use_dma , "i");
+module_param(io, int, 0);
+module_param(irq, int, 0);
+module_param(debug, int, 0);
+module_param_string(media, media, sizeof(media), 0);
+module_param(duplex, int, 0);
+module_param(dma , int, 0);
+module_param(dmasize , int, 0);
+module_param(use_dma , int, 0);
 MODULE_PARM_DESC(io, "cs89x0 I/O base address");
 MODULE_PARM_DESC(irq, "cs89x0 IRQ number");
 #if DEBUGGING
@@ -1743,8 +1905,7 @@ MODULE_LICENSE("GPL");
 
 */
 
-int
-init_module(void)
+int __init init_module(void)
 {
        struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
        struct net_local *lp;
@@ -1806,13 +1967,6 @@ init_module(void)
        if (ret)
                goto out;
 
-        if (register_netdev(dev) != 0) {
-                printk(KERN_ERR "cs89x0.c: No card found at 0x%x\n", io);
-                ret = -ENXIO;
-               outw(PP_ChipID, dev->base_addr + ADD_PORT);
-               release_region(dev->base_addr, NETCARD_IO_EXTENT);
-               goto out;
-        }
        dev_cs89x0 = dev;
        return 0;
 out:
@@ -1820,16 +1974,16 @@ out:
        return ret;
 }
 
-void
+void __exit
 cleanup_module(void)
 {
        unregister_netdev(dev_cs89x0);
-       outw(PP_ChipID, dev_cs89x0->base_addr + ADD_PORT);
+       writeword(dev_cs89x0->base_addr, ADD_PORT, PP_ChipID);
        release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);
        free_netdev(dev_cs89x0);
 }
 #endif /* MODULE */
-\f
+
 /*
  * Local variables:
  *  version-control: t