mlx4_core: Support ICM tables in coherent memory
[pandora-kernel.git] / drivers / net / mac8390.c
index 06cb460..90b0c3e 100644 (file)
@@ -7,13 +7,15 @@
    This software may be used and distributed according to the terms of
    the GNU Public License, incorporated herein by reference.  */
 
-/* 2000-02-28: support added for Dayna and Kinetics cards by 
+/* 2000-02-28: support added for Dayna and Kinetics cards by
    A.G.deWijn@phys.uu.nl */
 /* 2000-04-04: support added for Dayna2 by bart@etpmod.phys.tue.nl */
 /* 2001-04-18: support for DaynaPort E/LC-M by rayk@knightsmanor.org */
 /* 2001-05-15: support for Cabletron ported from old daynaport driver
- * and fixed access to Sonic Sys card which masquerades as a Farallon 
+ * and fixed access to Sonic Sys card which masquerades as a Farallon
  * by rayk@knightsmanor.org */
+/* 2002-12-30: Try to support more cards, some clues from NetBSD driver */
+/* 2003-12-26: Make sure Asante cards always work. */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <asm/hwtest.h>
 #include <asm/macints.h>
 
-#include "8390.h"
+static char version[] =
+       "mac8390.c: v0.4 2001-05-15 David Huggins-Daines <dhd@debian.org> and others\n";
+
+#define EI_SHIFT(x)    (ei_local->reg_offset[x])
+#define ei_inb(port)   in_8(port)
+#define ei_outb(val,port)  out_8(port,val)
+#define ei_inb_p(port)   in_8(port)
+#define ei_outb_p(val,port)  out_8(port,val)
+
+#include "lib8390.c"
 
 #define WD_START_PG                    0x00    /* First page of TX buffer */
 #define CABLETRON_RX_START_PG          0x00    /* First page of RX buffer */
 #define DAYNA_8390_BASE                0x80000
 #define DAYNA_8390_MEM         0x00000
 
-#define KINETICS_8390_BASE     0x80000
-#define KINETICS_8390_MEM      0x00000
-
-#define CABLETRON_8390_BASE    0x90000 
+#define CABLETRON_8390_BASE    0x90000
 #define CABLETRON_8390_MEM     0x00000
 
+#define INTERLAN_8390_BASE     0xE0000
+#define INTERLAN_8390_MEM      0xD0000
+
 enum mac8390_type {
        MAC8390_NONE = -1,
        MAC8390_APPLE,
        MAC8390_ASANTE,
-       MAC8390_FARALLON,  /* Apple, Asante, and Farallon are all compatible */
+       MAC8390_FARALLON,
        MAC8390_CABLETRON,
        MAC8390_DAYNA,
        MAC8390_INTERLAN,
        MAC8390_KINETICS,
-       MAC8390_FOCUS,
-       MAC8390_SONICSYS,
-       MAC8390_DAYNA2,
-       MAC8390_DAYNA3,
 };
 
 static const char * cardname[] = {
@@ -81,10 +88,6 @@ static const char * cardname[] = {
        "dayna",
        "interlan",
        "kinetics",
-       "focus",
-       "sonic systems",
-       "dayna2",
-       "dayna_lc",
 };
 
 static int word16[] = {
@@ -95,10 +98,6 @@ static int word16[] = {
        0, /* dayna */
        1, /* interlan */
        0, /* kinetics */
-       1, /* focus (??) */
-       1, /* sonic systems  */
-       1, /* dayna2 */
-       1, /* dayna-lc */
 };
 
 /* on which cards do we use NuBus resources? */
@@ -110,15 +109,14 @@ static int useresources[] = {
        0, /* dayna */
        0, /* interlan */
        0, /* kinetics */
-       0, /* focus (??) */
-       1, /* sonic systems */
-       1, /* dayna2 */
-       1, /* dayna-lc */
 };
 
-static char version[] __initdata =
-       "mac8390.c: v0.4 2001-05-15 David Huggins-Daines <dhd@debian.org> and others\n";
-               
+enum mac8390_access {
+       ACCESS_UNKNOWN = 0,
+       ACCESS_32,
+       ACCESS_16,
+};
+
 extern enum mac8390_type mac8390_ident(struct nubus_dev * dev);
 extern int mac8390_memsize(unsigned long membase);
 extern int mac8390_memtest(struct net_device * dev);
@@ -128,8 +126,9 @@ static int mac8390_initdev(struct net_device * dev, struct nubus_dev * ndev,
 static int mac8390_open(struct net_device * dev);
 static int mac8390_close(struct net_device * dev);
 static void mac8390_no_reset(struct net_device *dev);
+static void interlan_reset(struct net_device *dev);
 
-/* Sane (32-bit chunk memory read/write) - Apple/Asante/Farallon do this*/
+/* Sane (32-bit chunk memory read/write) - Some Farallon and Apple do this*/
 static void sane_get_8390_hdr(struct net_device *dev,
                              struct e8390_pkt_hdr *hdr, int ring_page);
 static void sane_block_input(struct net_device * dev, int count,
@@ -166,28 +165,98 @@ static void word_memcpy_fromcard(void *tp, const void *fp, int count);
 
 enum mac8390_type __init mac8390_ident(struct nubus_dev * dev)
 {
-       if (dev->dr_sw == NUBUS_DRSW_ASANTE)
-               return MAC8390_ASANTE;
-       if (dev->dr_sw == NUBUS_DRSW_FARALLON) 
-               return MAC8390_FARALLON;
-       if (dev->dr_sw == NUBUS_DRSW_KINETICS)
-               return MAC8390_KINETICS;
-       if (dev->dr_sw == NUBUS_DRSW_DAYNA)
-               return MAC8390_DAYNA;
-       if (dev->dr_sw == NUBUS_DRSW_DAYNA2)
-               return MAC8390_DAYNA2;
-       if (dev->dr_sw == NUBUS_DRSW_DAYNA_LC)
-               return MAC8390_DAYNA3;
-       if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
-               return MAC8390_CABLETRON;
+       switch (dev->dr_sw) {
+               case NUBUS_DRSW_3COM:
+                       switch (dev->dr_hw) {
+                               case NUBUS_DRHW_APPLE_SONIC_NB:
+                               case NUBUS_DRHW_APPLE_SONIC_LC:
+                               case NUBUS_DRHW_SONNET:
+                                       return MAC8390_NONE;
+                                       break;
+                               default:
+                                       return MAC8390_APPLE;
+                                       break;
+                       }
+                       break;
+
+               case NUBUS_DRSW_APPLE:
+                       switch (dev->dr_hw) {
+                               case NUBUS_DRHW_ASANTE_LC:
+                                       return MAC8390_NONE;
+                                       break;
+                               case NUBUS_DRHW_CABLETRON:
+                                       return MAC8390_CABLETRON;
+                                       break;
+                               default:
+                                       return MAC8390_APPLE;
+                                       break;
+                       }
+                       break;
+
+               case NUBUS_DRSW_ASANTE:
+                       return MAC8390_ASANTE;
+                       break;
+
+               case NUBUS_DRSW_TECHWORKS:
+               case NUBUS_DRSW_DAYNA2:
+               case NUBUS_DRSW_DAYNA_LC:
+                       if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
+                               return MAC8390_CABLETRON;
+                       else
+                               return MAC8390_APPLE;
+                       break;
+
+               case NUBUS_DRSW_FARALLON:
+                       return MAC8390_FARALLON;
+                       break;
+
+               case NUBUS_DRSW_KINETICS:
+                       switch (dev->dr_hw) {
+                               case NUBUS_DRHW_INTERLAN:
+                                       return MAC8390_INTERLAN;
+                                       break;
+                               default:
+                                       return MAC8390_KINETICS;
+                                       break;
+                       }
+                       break;
+
+               case NUBUS_DRSW_DAYNA:
+                       // These correspond to Dayna Sonic cards
+                       // which use the macsonic driver
+                       if (dev->dr_hw == NUBUS_DRHW_SMC9194 ||
+                               dev->dr_hw == NUBUS_DRHW_INTERLAN )
+                               return MAC8390_NONE;
+                       else
+                               return MAC8390_DAYNA;
+                       break;
+       }
        return MAC8390_NONE;
 }
 
+enum mac8390_access __init mac8390_testio(volatile unsigned long membase)
+{
+       unsigned long outdata = 0xA5A0B5B0;
+       unsigned long indata =  0x00000000;
+       /* Try writing 32 bits */
+       memcpy((char *)membase, (char *)&outdata, 4);
+       /* Now compare them */
+       if (memcmp((char *)&outdata, (char *)membase, 4) == 0)
+               return ACCESS_32;
+       /* Write 16 bit output */
+       word_memcpy_tocard((char *)membase, (char *)&outdata, 4);
+       /* Now read it back */
+       word_memcpy_fromcard((char *)&indata, (char *)membase, 4);
+       if (outdata == indata)
+               return ACCESS_16;
+       return ACCESS_UNKNOWN;
+}
+
 int __init mac8390_memsize(unsigned long membase)
 {
        unsigned long flags;
        int i, j;
-       
+
        local_irq_save(flags);
        /* Check up to 32K in 4K increments */
        for (i = 0; i < 8; i++) {
@@ -197,7 +266,7 @@ int __init mac8390_memsize(unsigned long membase)
                   RAM end located */
                if (hwreg_present(m) == 0)
                        break;
-               
+
                /* write a distinctive byte */
                *m = 0xA5A0 | i;
                /* check that we read back what we wrote */
@@ -224,7 +293,7 @@ struct net_device * __init mac8390_probe(int unit)
        int version_disp = 0;
        struct nubus_dev * ndev = NULL;
        int err = -ENODEV;
-       
+
        struct nubus_dir dir;
        struct nubus_dirent ent;
        int offset;
@@ -237,7 +306,7 @@ struct net_device * __init mac8390_probe(int unit)
        if (!MACH_IS_MAC)
                return ERR_PTR(-ENODEV);
 
-       dev = alloc_ei_netdev();
+       dev = ____alloc_ei_netdev(0);
        if (!dev)
                return ERR_PTR(-ENOMEM);
 
@@ -273,7 +342,7 @@ struct net_device * __init mac8390_probe(int unit)
                               dev->name, ndev->board->slot);
                        continue;
                }
-               
+
                /* Get the MAC address */
                if ((nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent)) == -1) {
                        printk(KERN_INFO "%s: Couldn't get MAC address!\n",
@@ -281,16 +350,8 @@ struct net_device * __init mac8390_probe(int unit)
                        continue;
                } else {
                        nubus_get_rsrc_mem(dev->dev_addr, &ent, 6);
-                       /* Some Sonic Sys cards masquerade as Farallon */
-                       if (cardtype == MAC8390_FARALLON && 
-                                       dev->dev_addr[0] == 0x0 &&
-                                       dev->dev_addr[1] == 0x40 &&
-                                       dev->dev_addr[2] == 0x10) {
-                               /* This is really Sonic Sys card */
-                               cardtype = MAC8390_SONICSYS;
-                       }
                }
-               
+
                if (useresources[cardtype] == 1) {
                        nubus_rewinddir(&dir);
                        if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_BASEOS, &ent) == -1) {
@@ -318,16 +379,27 @@ struct net_device * __init mac8390_probe(int unit)
                        switch (cardtype) {
                                case MAC8390_KINETICS:
                                case MAC8390_DAYNA: /* it's the same */
-                                       dev->base_addr = 
+                                       dev->base_addr =
                                                (int)(ndev->board->slot_addr +
                                                DAYNA_8390_BASE);
-                                       dev->mem_start = 
+                                       dev->mem_start =
                                                (int)(ndev->board->slot_addr +
                                                DAYNA_8390_MEM);
                                        dev->mem_end =
                                                dev->mem_start +
                                                mac8390_memsize(dev->mem_start);
                                        break;
+                               case MAC8390_INTERLAN:
+                                       dev->base_addr =
+                                               (int)(ndev->board->slot_addr +
+                                               INTERLAN_8390_BASE);
+                                       dev->mem_start =
+                                               (int)(ndev->board->slot_addr +
+                                               INTERLAN_8390_MEM);
+                                       dev->mem_end =
+                                               dev->mem_start +
+                                               mac8390_memsize(dev->mem_start);
+                                       break;
                                case MAC8390_CABLETRON:
                                        dev->base_addr =
                                                (int)(ndev->board->slot_addr +
@@ -343,15 +415,15 @@ struct net_device * __init mac8390_probe(int unit)
                                         */
                                        i = (void *)dev->base_addr;
                                        *i = 0x21;
-                                       dev->mem_end = 
+                                       dev->mem_end =
                                                dev->mem_start +
                                                mac8390_memsize(dev->mem_start);
                                        break;
-                                       
+
                                default:
                                        printk(KERN_ERR "Card type %s is"
-                                                       " unsupported, sorry\n",
-                                              cardname[cardtype]);
+                                              " unsupported, sorry\n",
+                                              ndev->board->name);
                                        continue;
                        }
                }
@@ -432,13 +504,13 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
                24,    26,     28,     30
        };
 
-       int access_bitmode;
-       
+       int access_bitmode = 0;
+
        /* Now fill in our stuff */
        dev->open = &mac8390_open;
        dev->stop = &mac8390_close;
 #ifdef CONFIG_NET_POLL_CONTROLLER
-       dev->poll_controller = ei_poll;
+       dev->poll_controller = __ei_poll;
 #endif
 
        /* GAR, ei_status is actually a macro even though it looks global */
@@ -459,32 +531,50 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
                ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
                ei_status.rmem_end = dev->mem_end;
        }
-       
+
        /* Fill in model-specific information and functions */
        switch(type) {
-       case MAC8390_SONICSYS:
-               /* 16 bit card, register map is reversed */
-               ei_status.reset_8390 = &mac8390_no_reset;
-               ei_status.block_input = &slow_sane_block_input;
-               ei_status.block_output = &slow_sane_block_output;
-               ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
-               ei_status.reg_offset = back4_offsets;
-               access_bitmode = 0;
-               break;
        case MAC8390_FARALLON:
        case MAC8390_APPLE:
+               switch(mac8390_testio(dev->mem_start)) {
+                       case ACCESS_UNKNOWN:
+                               printk("Don't know how to access card memory!\n");
+                               return -ENODEV;
+                               break;
+
+                       case ACCESS_16:
+                               /* 16 bit card, register map is reversed */
+                               ei_status.reset_8390 = &mac8390_no_reset;
+                               ei_status.block_input = &slow_sane_block_input;
+                               ei_status.block_output = &slow_sane_block_output;
+                               ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+                               ei_status.reg_offset = back4_offsets;
+                               break;
+
+                       case ACCESS_32:
+                               /* 32 bit card, register map is reversed */
+                               ei_status.reset_8390 = &mac8390_no_reset;
+                               ei_status.block_input = &sane_block_input;
+                               ei_status.block_output = &sane_block_output;
+                               ei_status.get_8390_hdr = &sane_get_8390_hdr;
+                               ei_status.reg_offset = back4_offsets;
+                               access_bitmode = 1;
+                               break;
+               }
+               break;
+
        case MAC8390_ASANTE:
-       case MAC8390_DAYNA2:
-       case MAC8390_DAYNA3:
-               /* 32 bit card, register map is reversed */
-               /* sane */
+               /* Some Asante cards pass the 32 bit test
+                * but overwrite system memory when run at 32 bit.
+                * so we run them all at 16 bit.
+                */
                ei_status.reset_8390 = &mac8390_no_reset;
-               ei_status.block_input = &sane_block_input;
-               ei_status.block_output = &sane_block_output;
-               ei_status.get_8390_hdr = &sane_get_8390_hdr;
+               ei_status.block_input = &slow_sane_block_input;
+               ei_status.block_output = &slow_sane_block_output;
+               ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
                ei_status.reg_offset = back4_offsets;
-               access_bitmode = 1;
                break;
+
        case MAC8390_CABLETRON:
                /* 16 bit card, register map is short forward */
                ei_status.reset_8390 = &mac8390_no_reset;
@@ -492,25 +582,34 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
                ei_status.block_output = &slow_sane_block_output;
                ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
                ei_status.reg_offset = fwrd2_offsets;
-               access_bitmode = 0;
                break;
+
        case MAC8390_DAYNA:
        case MAC8390_KINETICS:
-               /* 16 bit memory */
+               /* 16 bit memory, register map is forward */
                /* dayna and similar */
                ei_status.reset_8390 = &mac8390_no_reset;
                ei_status.block_input = &dayna_block_input;
                ei_status.block_output = &dayna_block_output;
                ei_status.get_8390_hdr = &dayna_get_8390_hdr;
                ei_status.reg_offset = fwrd4_offsets;
-               access_bitmode = 0;
                break;
+
+       case MAC8390_INTERLAN:
+               /* 16 bit memory, register map is forward */
+               ei_status.reset_8390 = &interlan_reset;
+               ei_status.block_input = &slow_sane_block_input;
+               ei_status.block_output = &slow_sane_block_output;
+               ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+               ei_status.reg_offset = fwrd4_offsets;
+               break;
+
        default:
-               printk(KERN_ERR "Card type %s is unsupported, sorry\n", cardname[type]);
+               printk(KERN_ERR "Card type %s is unsupported, sorry\n", ndev->board->name);
                return -ENODEV;
        }
-               
-       NS8390_init(dev, 0);
+
+       __NS8390_init(dev, 0);
 
        /* Good, done, now spit out some messages */
        printk(KERN_INFO "%s: %s in slot %X (type %s)\n",
@@ -524,26 +623,26 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
                                printk(":");
                }
        }
-       printk(" IRQ %d, shared memory at %#lx-%#lx,  %d-bit access.\n",
-                  dev->irq, dev->mem_start, dev->mem_end-1, 
-                  access_bitmode?32:16);
+       printk(" IRQ %d, %d KB shared memory at %#lx,  %d-bit access.\n",
+                  dev->irq, (int)((dev->mem_end - dev->mem_start)/0x1000) * 4,
+                  dev->mem_start, access_bitmode?32:16);
        return 0;
 }
 
 static int mac8390_open(struct net_device *dev)
 {
-       ei_open(dev);
-       if (request_irq(dev->irq, ei_interrupt, 0, "8390 Ethernet", dev)) {
+       __ei_open(dev);
+       if (request_irq(dev->irq, __ei_interrupt, 0, "8390 Ethernet", dev)) {
                printk ("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
                return -EAGAIN;
-       }       
+       }
        return 0;
 }
 
 static int mac8390_close(struct net_device *dev)
 {
        free_irq(dev->irq, dev);
-       ei_close(dev);
+       __ei_close(dev);
        return 0;
 }
 
@@ -555,6 +654,18 @@ static void mac8390_no_reset(struct net_device *dev)
        return;
 }
 
+static void interlan_reset(struct net_device *dev)
+{
+       unsigned char *target=nubus_slot_addr(IRQ2SLOT(dev->irq));
+       if (ei_debug > 1)
+               printk("Need to reset the NS8390 t=%lu...", jiffies);
+       ei_status.txing = 0;
+       target[0xC0000] = 0;
+       if (ei_debug > 1)
+               printk("reset complete\n");
+       return;
+}
+
 /* dayna_memcpy_fromio/dayna_memcpy_toio */
 /* directly from daynaport.c by Alan Cox */
 static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count)
@@ -639,7 +750,7 @@ static void sane_block_output(struct net_device *dev, int count,
                              const unsigned char *buf, int start_page)
 {
        long shmem = (start_page - WD_START_PG)<<8;
-       
+
        memcpy_toio((char *)dev->mem_start + shmem, buf, count);
 }
 
@@ -681,12 +792,12 @@ static void dayna_block_output(struct net_device *dev, int count, const unsigned
                                int start_page)
 {
        long shmem = (start_page - WD_START_PG)<<8;
-       
+
        dayna_memcpy_tocard(dev, shmem, buf, count);
 }
 
 /* Cabletron block I/O */
-static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, 
+static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
        int ring_page)
 {
        unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
@@ -750,4 +861,4 @@ static void word_memcpy_fromcard(void *tp, const void *fp, int count)
                *to++=*from++;
 }
 
-       
+