m68k: Mac DP8390 update

Fix the support for C/NET nubus ethernet cards etc. Sync up the DP8390 driver
with the latest code in the mac68k repo.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Finn Thain 2007-05-01 22:32:54 +02:00 committed by Linus Torvalds
parent f877958879
commit 2964db0f59

View file

@ -14,6 +14,8 @@
/* 2001-05-15: support for Cabletron ported from old daynaport driver /* 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 */ * 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/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
@ -61,25 +63,21 @@ static char version[] =
#define DAYNA_8390_BASE 0x80000 #define DAYNA_8390_BASE 0x80000
#define DAYNA_8390_MEM 0x00000 #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 CABLETRON_8390_MEM 0x00000
#define INTERLAN_8390_BASE 0xE0000
#define INTERLAN_8390_MEM 0xD0000
enum mac8390_type { enum mac8390_type {
MAC8390_NONE = -1, MAC8390_NONE = -1,
MAC8390_APPLE, MAC8390_APPLE,
MAC8390_ASANTE, MAC8390_ASANTE,
MAC8390_FARALLON, /* Apple, Asante, and Farallon are all compatible */ MAC8390_FARALLON,
MAC8390_CABLETRON, MAC8390_CABLETRON,
MAC8390_DAYNA, MAC8390_DAYNA,
MAC8390_INTERLAN, MAC8390_INTERLAN,
MAC8390_KINETICS, MAC8390_KINETICS,
MAC8390_FOCUS,
MAC8390_SONICSYS,
MAC8390_DAYNA2,
MAC8390_DAYNA3,
}; };
static const char * cardname[] = { static const char * cardname[] = {
@ -90,10 +88,6 @@ static const char * cardname[] = {
"dayna", "dayna",
"interlan", "interlan",
"kinetics", "kinetics",
"focus",
"sonic systems",
"dayna2",
"dayna_lc",
}; };
static int word16[] = { static int word16[] = {
@ -104,10 +98,6 @@ static int word16[] = {
0, /* dayna */ 0, /* dayna */
1, /* interlan */ 1, /* interlan */
0, /* kinetics */ 0, /* kinetics */
1, /* focus (??) */
1, /* sonic systems */
1, /* dayna2 */
1, /* dayna-lc */
}; };
/* on which cards do we use NuBus resources? */ /* on which cards do we use NuBus resources? */
@ -119,10 +109,12 @@ static int useresources[] = {
0, /* dayna */ 0, /* dayna */
0, /* interlan */ 0, /* interlan */
0, /* kinetics */ 0, /* kinetics */
0, /* focus (??) */ };
1, /* sonic systems */
1, /* dayna2 */ enum mac8390_access {
1, /* dayna-lc */ ACCESS_UNKNOWN = 0,
ACCESS_32,
ACCESS_16,
}; };
extern enum mac8390_type mac8390_ident(struct nubus_dev * dev); extern enum mac8390_type mac8390_ident(struct nubus_dev * dev);
@ -134,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_open(struct net_device * dev);
static int mac8390_close(struct net_device * dev); static int mac8390_close(struct net_device * dev);
static void mac8390_no_reset(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, static void sane_get_8390_hdr(struct net_device *dev,
struct e8390_pkt_hdr *hdr, int ring_page); struct e8390_pkt_hdr *hdr, int ring_page);
static void sane_block_input(struct net_device * dev, int count, static void sane_block_input(struct net_device * dev, int count,
@ -172,21 +165,91 @@ static void word_memcpy_fromcard(void *tp, const void *fp, int count);
enum mac8390_type __init mac8390_ident(struct nubus_dev * dev) enum mac8390_type __init mac8390_ident(struct nubus_dev * dev)
{ {
if (dev->dr_sw == NUBUS_DRSW_ASANTE) 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; return MAC8390_ASANTE;
if (dev->dr_sw == NUBUS_DRSW_FARALLON) break;
return MAC8390_FARALLON;
if (dev->dr_sw == NUBUS_DRSW_KINETICS) case NUBUS_DRSW_TECHWORKS:
return MAC8390_KINETICS; case NUBUS_DRSW_DAYNA2:
if (dev->dr_sw == NUBUS_DRSW_DAYNA) case NUBUS_DRSW_DAYNA_LC:
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) if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
return MAC8390_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; 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) int __init mac8390_memsize(unsigned long membase)
@ -287,14 +350,6 @@ struct net_device * __init mac8390_probe(int unit)
continue; continue;
} else { } else {
nubus_get_rsrc_mem(dev->dev_addr, &ent, 6); 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) { if (useresources[cardtype] == 1) {
@ -334,6 +389,17 @@ struct net_device * __init mac8390_probe(int unit)
dev->mem_start + dev->mem_start +
mac8390_memsize(dev->mem_start); mac8390_memsize(dev->mem_start);
break; 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: case MAC8390_CABLETRON:
dev->base_addr = dev->base_addr =
(int)(ndev->board->slot_addr + (int)(ndev->board->slot_addr +
@ -357,7 +423,7 @@ struct net_device * __init mac8390_probe(int unit)
default: default:
printk(KERN_ERR "Card type %s is" printk(KERN_ERR "Card type %s is"
" unsupported, sorry\n", " unsupported, sorry\n",
cardname[cardtype]); ndev->board->name);
continue; continue;
} }
} }
@ -438,7 +504,7 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
24, 26, 28, 30 24, 26, 28, 30
}; };
int access_bitmode; int access_bitmode = 0;
/* Now fill in our stuff */ /* Now fill in our stuff */
dev->open = &mac8390_open; dev->open = &mac8390_open;
@ -468,22 +534,25 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
/* Fill in model-specific information and functions */ /* Fill in model-specific information and functions */
switch(type) { switch(type) {
case MAC8390_SONICSYS: 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 */ /* 16 bit card, register map is reversed */
ei_status.reset_8390 = &mac8390_no_reset; ei_status.reset_8390 = &mac8390_no_reset;
ei_status.block_input = &slow_sane_block_input; ei_status.block_input = &slow_sane_block_input;
ei_status.block_output = &slow_sane_block_output; ei_status.block_output = &slow_sane_block_output;
ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
ei_status.reg_offset = back4_offsets; ei_status.reg_offset = back4_offsets;
access_bitmode = 0;
break; break;
case MAC8390_FARALLON:
case MAC8390_APPLE: case ACCESS_32:
case MAC8390_ASANTE:
case MAC8390_DAYNA2:
case MAC8390_DAYNA3:
/* 32 bit card, register map is reversed */ /* 32 bit card, register map is reversed */
/* sane */
ei_status.reset_8390 = &mac8390_no_reset; ei_status.reset_8390 = &mac8390_no_reset;
ei_status.block_input = &sane_block_input; ei_status.block_input = &sane_block_input;
ei_status.block_output = &sane_block_output; ei_status.block_output = &sane_block_output;
@ -491,6 +560,21 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
ei_status.reg_offset = back4_offsets; ei_status.reg_offset = back4_offsets;
access_bitmode = 1; access_bitmode = 1;
break; break;
}
break;
case MAC8390_ASANTE:
/* 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 = &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 MAC8390_CABLETRON: case MAC8390_CABLETRON:
/* 16 bit card, register map is short forward */ /* 16 bit card, register map is short forward */
ei_status.reset_8390 = &mac8390_no_reset; ei_status.reset_8390 = &mac8390_no_reset;
@ -498,21 +582,30 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
ei_status.block_output = &slow_sane_block_output; ei_status.block_output = &slow_sane_block_output;
ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
ei_status.reg_offset = fwrd2_offsets; ei_status.reg_offset = fwrd2_offsets;
access_bitmode = 0;
break; break;
case MAC8390_DAYNA: case MAC8390_DAYNA:
case MAC8390_KINETICS: case MAC8390_KINETICS:
/* 16 bit memory */ /* 16 bit memory, register map is forward */
/* dayna and similar */ /* dayna and similar */
ei_status.reset_8390 = &mac8390_no_reset; ei_status.reset_8390 = &mac8390_no_reset;
ei_status.block_input = &dayna_block_input; ei_status.block_input = &dayna_block_input;
ei_status.block_output = &dayna_block_output; ei_status.block_output = &dayna_block_output;
ei_status.get_8390_hdr = &dayna_get_8390_hdr; ei_status.get_8390_hdr = &dayna_get_8390_hdr;
ei_status.reg_offset = fwrd4_offsets; ei_status.reg_offset = fwrd4_offsets;
access_bitmode = 0;
break; 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: 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; return -ENODEV;
} }
@ -530,9 +623,9 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
printk(":"); printk(":");
} }
} }
printk(" IRQ %d, shared memory at %#lx-%#lx, %d-bit access.\n", printk(" IRQ %d, %d KB shared memory at %#lx, %d-bit access.\n",
dev->irq, dev->mem_start, dev->mem_end-1, dev->irq, (int)((dev->mem_end - dev->mem_start)/0x1000) * 4,
access_bitmode?32:16); dev->mem_start, access_bitmode?32:16);
return 0; return 0;
} }
@ -561,6 +654,18 @@ static void mac8390_no_reset(struct net_device *dev)
return; 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 */ /* dayna_memcpy_fromio/dayna_memcpy_toio */
/* directly from daynaport.c by Alan Cox */ /* directly from daynaport.c by Alan Cox */
static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count) static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count)