Subject: [patch 20/33] m68k: Mac DP8390 update

From: Geert Uytterhoeven <[email-masked]>
Date: Tue, 01 May 2007 22:32:54 +0200

From: Finn Thain <[email-masked]>

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 <[email-masked]>
Signed-off-by: Geert Uytterhoeven <[email-masked]>
---
 drivers/net/mac8390.c |  245 +++++++++++++++++++++++++++++++++++---------------
 1 file changed, 175 insertions(+), 70 deletions(-)

--- linux-m68k-2.6.21.orig/drivers/net/mac8390.c
+++ linux-m68k-2.6.21/drivers/net/mac8390.c
@@ -14,6 +14,8 @@
 /* 2001-05-15: support for Cabletron ported from old daynaport driver
  * and fixed access to Sonic Sys card which masquerades as a Farallon
  * by [email-masked] */
+/* 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>
@@ -61,25 +63,21 @@ static char version[] =
 #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_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[] = {
@@ -90,10 +88,6 @@ static const char * cardname[] = {
 	"dayna",
 	"interlan",
 	"kinetics",
-	"focus",
-	"sonic systems",
-	"dayna2",
-	"dayna_lc",
 };
 
 static int word16[] = {
@@ -104,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? */
@@ -119,10 +109,12 @@ static int useresources[] = {
 	0, /* dayna */
 	0, /* interlan */
 	0, /* kinetics */
-	0, /* focus (??) */
-	1, /* sonic systems */
-	1, /* dayna2 */
-	1, /* dayna-lc */
+};
+
+enum mac8390_access {
+	ACCESS_UNKNOWN = 0,
+	ACCESS_32,
+	ACCESS_16,
 };
 
 extern enum mac8390_type mac8390_ident(struct nubus_dev * dev);
@@ -134,8 +126,9 @@ static int mac8390_initdev(struct net_de
 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,
@@ -172,23 +165,93 @@ static void word_memcpy_fromcard(void *t
 
 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;
@@ -287,14 +350,6 @@ struct net_device * __init mac8390_probe
 			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) {
@@ -334,6 +389,17 @@ struct net_device * __init mac8390_probe
 						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 +
@@ -356,8 +422,8 @@ struct net_device * __init mac8390_probe
 
 				default:
 					printk(KERN_ERR "Card type %s is"
-							" unsupported, sorry\n",
-					       cardname[cardtype]);
+					       " unsupported, sorry\n",
+					       ndev->board->name);
 					continue;
 			}
 		}
@@ -438,7 +504,7 @@ static int __init mac8390_initdev(struct
 		24,    26,     28,     30
 	};
 
-	int access_bitmode;
+	int access_bitmode = 0;
 
 	/* Now fill in our stuff */
 	dev->open = &mac8390_open;
@@ -468,29 +534,47 @@ static int __init mac8390_initdev(struct
 
 	/* 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;
@@ -498,21 +582,30 @@ static int __init mac8390_initdev(struct
 		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;
 	}
 
@@ -530,9 +623,9 @@ static int __init mac8390_initdev(struct
 				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;
 }
 
@@ -561,6 +654,18 @@ static void mac8390_no_reset(struct net_
 	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)

--
Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email-masked]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds