patch-2.3.42 linux/drivers/net/daynaport.c
Next file: linux/drivers/net/irda/Config.in
Previous file: linux/drivers/net/cs89x0.h
Back to the patch index
Back to the overall index
- Lines: 773
- Date:
Mon Jan 31 10:34:12 2000
- Orig file:
v2.3.41/linux/drivers/net/daynaport.c
- Orig date:
Wed Aug 18 11:36:41 1999
diff -u --recursive --new-file v2.3.41/linux/drivers/net/daynaport.c linux/drivers/net/daynaport.c
@@ -1,4 +1,4 @@
-/* mac_ns8390.c: A Macintosh 8390 based ethernet driver for linux. */
+/* daynaport.c: A Macintosh 8390 based ethernet driver for linux. */
/*
Derived from code:
@@ -15,14 +15,20 @@
The block output routines may be wrong for non Dayna
cards
- Reading MAC addresses
-*/
+ Fix this driver so that it will attempt to use the info
+ (i.e. iobase, iosize) given to it by the new and improved
+ NuBus code.
+
+ Despite its misleading filename, this driver is not Dayna-specific
+ anymore. */
+/* Cabletron E6100 card support added by Tony Mantler (eek@escape.ca) April 1999 */
static const char *version =
- "mac_ns8390.c:v0.01 7/5/97 Alan Cox (Alan.Cox@linux.org)\n";
+ "daynaport.c: v0.02 1999-05-17 Alan Cox (Alan.Cox@linux.org) and others\n";
+static int version_printed = 0;
#include <linux/module.h>
-
+#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
@@ -31,20 +37,26 @@
#include <asm/io.h>
#include <asm/system.h>
#include <asm/hwtest.h>
+#include <asm/macints.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include "8390.h"
-int ns8390_probe1(struct net_device *dev, int word16, char *name, int id, int prom);
+extern int console_loglevel;
+
+int ns8390_probe1(struct net_device *dev, int word16, char *name, int id,
+ int prom, struct nubus_dev *ndev);
static int ns8390_open(struct net_device *dev);
static void ns8390_no_reset(struct net_device *dev);
static int ns8390_close_card(struct net_device *dev);
+/* Interlan */
static void interlan_reset(struct net_device *dev);
+/* Dayna */
static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
int ring_page);
static void dayna_block_input(struct net_device *dev, int count,
@@ -52,6 +64,7 @@
static void dayna_block_output(struct net_device *dev, int count,
const unsigned char *buf, const int start_page);
+/* Sane (32-bit chunk memory read/write) */
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,
@@ -59,6 +72,7 @@
static void sane_block_output(struct net_device *dev, int count,
const unsigned char *buf, const int start_page);
+/* Slow Sane (16-bit chunk memory read/write) */
static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
int ring_page);
static void slow_sane_block_input(struct net_device *dev, int count,
@@ -71,6 +85,10 @@
#define WD03_STOP_PG 0x20 /* Last page +1 of RX ring */
#define WD13_STOP_PG 0x40 /* Last page +1 of RX ring */
+#define CABLETRON_RX_START_PG 0x00 /* First page of RX buffer */
+#define CABLETRON_RX_STOP_PG 0x30 /* Last page +1 of RX ring */
+#define CABLETRON_TX_START_PG CABLETRON_RX_STOP_PG /* First page of TX buffer */
+
#define DAYNA_MAC_BASE 0xf0007
#define DAYNA_8390_BASE 0x80000 /* 3 */
@@ -81,9 +99,14 @@
#define APPLE_8390_MEM 0xD0000
#define APPLE_MEMSIZE 8192 /* FIXME: need to dynamically check */
-#define KINETICS_8390_BASE 0x80003
-#define KINETICS_8390_MEM 0x00000
+#define KINETICS_MAC_BASE 0xf0004 /* first byte of each long */
+#define KINETICS_8390_BASE 0x80000
+#define KINETICS_8390_MEM 0x00000 /* first word of each long */
#define KINETICS_MEMSIZE 8192 /* FIXME: need to dynamically check */
+/*#define KINETICS_MEMSIZE (0x10000/2) * CSA: on the board I have, at least */
+
+#define CABLETRON_8390_BASE 0x90000
+#define CABLETRON_8390_MEM 0x00000
static int test_8390(volatile char *ptr, int scale)
{
@@ -113,34 +136,59 @@
* Identify the species of NS8390 card/driver we need
*/
-#define NS8390_DAYNA 1
-#define NS8390_INTERLAN 2
-#define NS8390_KINETICS 3
-#define NS8390_APPLE 4
-#define NS8390_FARALLON 5
-#define NS8390_ASANTE 6
-
-int ns8390_ident(struct nubus_type *nb)
-{
- /* It appears anything with a software type of 0 is an apple
- compatible - even if the hardware matches others */
-
- if(nb->DrSW==0x0001 || nb->DrSW==0x0109 || nb->DrSW==0x0000 || nb->DrSW==0x0100)
- return NS8390_APPLE;
-
+enum mac8390_type {
+ NS8390_DAYNA,
+ NS8390_INTERLAN,
+ NS8390_KINETICS,
+ NS8390_APPLE,
+ NS8390_FARALLON,
+ NS8390_ASANTE,
+ NS8390_CABLETRON
+};
+
+int __init ns8390_ident(struct nubus_dev* ndev)
+{
+ /* This really needs to be tested and tested hard. */
+
+ /* Summary of what we know so far --
+ * SW: 0x0104 -- asante, 16 bit, back4_offsets
+ * SW: 0x010b -- daynaport, 16 bit, fwrd4_offsets
+ * SW: 0x010c -- farallon, 16 bit, back4_offsets, no long word access
+ * SW: 0x011a -- focus, [no details yet]
+ * SW: ?????? -- interlan, 16 bit, back4_offsets, funny reset
+ * SW: ?????? -- kinetics, 8 bit, back4_offsets
+ * -- so i've this hypothesis going that says DrSW&1 says whether the
+ * map is forward or backwards -- and maybe DrSW&256 says what the
+ * register spacing is -- for all cards that report a DrSW in some
+ * range.
+ * This would allow the "apple compatible" driver to drive many
+ * seemingly different types of cards. More DrSW info is needed
+ * to investigate this properly. [CSA, 21-May-1999]
+ */
/* Dayna ex Kinetics board */
- if(nb->DrHW==0x0103)
+ if(ndev->dr_sw == NUBUS_DRSW_DAYNA)
return NS8390_DAYNA;
-
- /* Asante board */
- if(nb->DrHW==0x0104)
+ if(ndev->dr_sw == NUBUS_DRSW_ASANTE)
return NS8390_ASANTE;
- if(nb->DrHW==0x0100)
- return NS8390_INTERLAN;
- if(nb->DrHW==0x0106)
- return NS8390_KINETICS;
- if(nb->DrSW==0x010C)
+ if(ndev->dr_sw == NUBUS_DRSW_FARALLON) /* farallon or sonic systems */
return NS8390_FARALLON;
+ if(ndev->dr_sw == NUBUS_DRSW_KINETICS)
+ return NS8390_KINETICS;
+ /* My ATI Engineering card with this combination crashes the */
+ /* driver trying to xmit packets. Best not touch it for now. */
+ /* - 1999-05-20 (funaho@jurai.org) */
+ if(ndev->dr_sw == NUBUS_DRSW_FOCUS)
+ return -1;
+
+ /* Check the HW on this one, because it shares the same DrSW as
+ the on-board SONIC chips */
+ if(ndev->dr_hw == NUBUS_DRHW_CABLETRON)
+ return NS8390_CABLETRON;
+ /* does anyone have one of these? */
+ if(ndev->dr_hw == NUBUS_DRHW_INTERLAN)
+ return NS8390_INTERLAN;
+
+ /* FIXME: what do genuine Apple boards look like? */
return -1;
}
@@ -148,7 +196,7 @@
* Memory probe for 8390 cards
*/
-int apple_8390_mem_probe(volatile unsigned short *p)
+int __init apple_8390_mem_probe(volatile unsigned short *p)
{
int i, j;
/*
@@ -192,61 +240,79 @@
/*
* Probe for 8390 cards.
* The ns8390_probe1() routine initializes the card and fills the
- * station address field. On entry base_addr is set, irq is set
- * (These come from the nubus probe code). dev->mem_start points
+ * station address field.
+ *
+ * The NuBus interface has changed! We now scan for these somewhat
+ * like how the PCI and Zorro drivers do. It's not clear whether
+ * this is actually better, but it makes things more consistent.
+ *
+ * dev->mem_start points
* at the memory ring, dev->mem_end gives the end of it.
*/
-int ns8390_probe(struct nubus_device_specifier *d, int slot, struct nubus_type *match)
+int __init mac8390_probe(struct net_device *dev)
{
- struct net_device *dev;
+ static int slots = 0;
volatile unsigned short *i;
volatile unsigned char *p;
int plen;
int id;
+ static struct nubus_dev* ndev = NULL;
- if(match->category!=NUBUS_CAT_NETWORK || match->type!=1)
- return -ENODEV;
- /* Ok so it is an ethernet network device */
- if((id=ns8390_ident(match))==-1)
- {
- printk("Ethernet but type unknown %d\n",match->DrHW);
+ /* Find the first card that hasn't already been seen */
+ while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
+ NUBUS_TYPE_ETHERNET, ndev)) != NULL) {
+ /* Have we seen it already? */
+ if (slots & (1<<ndev->board->slot))
+ continue;
+ slots |= 1<<ndev->board->slot;
+
+ /* Is it one of ours? */
+ if ((id = ns8390_ident(ndev)) != -1)
+ break;
+ }
+
+ /* Hm. No more cards, then */
+ if (ndev == NULL)
return -ENODEV;
+
+ dev = init_etherdev(dev, 0);
+
+ if (!version_printed) {
+ printk(KERN_INFO "%s", version);
+ version_printed = 1;
}
- dev = init_etherdev(0, 0);
- if(dev==NULL)
- return -ENOMEM;
/*
* Dayna specific init
*/
if(id==NS8390_DAYNA)
{
- dev->base_addr=(int)(nubus_slot_addr(slot)+DAYNA_8390_BASE);
- dev->mem_start=(int)(nubus_slot_addr(slot)+DAYNA_8390_MEM);
- dev->mem_end=dev->mem_start+DAYNA_MEMSIZE; /* 8K it seems */
+ dev->base_addr = (int)(ndev->board->slot_addr+DAYNA_8390_BASE);
+ dev->mem_start = (int)(ndev->board->slot_addr+DAYNA_8390_MEM);
+ dev->mem_end = dev->mem_start+DAYNA_MEMSIZE; /* 8K it seems */
- printk("daynaport: testing board: ");
-
+ printk(KERN_INFO "%s: daynaport. testing board: ", dev->name);
+
printk("memory - ");
-
- i=(void *)dev->mem_start;
+
+ i = (void *)dev->mem_start;
memset((void *)i,0xAA, DAYNA_MEMSIZE);
while(i<(volatile unsigned short *)dev->mem_end)
{
if(*i!=0xAAAA)
goto membad;
- *i=0x5555;
- if(*i!=0x5555)
+ *i=0x5678; /* make sure we catch byte smearing */
+ if(*i!=0x5678)
goto membad;
i+=2; /* Skip a word */
}
-
+
printk("controller - ");
-
+
p=(void *)dev->base_addr;
plen=0;
-
+
while(plen<0x3FF00)
{
if(test_8390(p,0)==0)
@@ -263,26 +329,71 @@
if(plen==0x3FF00)
goto membad;
printk("OK\n");
- dev->irq=slot;
- if(ns8390_probe1(dev, 0, "dayna", id, -1)==0)
- return 0;
+ dev->irq = SLOT2IRQ(ndev->board->slot);
+ if(ns8390_probe1(dev, 0, "dayna", id, -1, ndev)==0)
+ return 0;
+ }
+ /* Cabletron */
+ if (id==NS8390_CABLETRON) {
+ int memsize = 16<<10; /* fix this */
+
+ dev->base_addr=(int)(ndev->board->slot_addr+CABLETRON_8390_BASE);
+ dev->mem_start=(int)(ndev->board->slot_addr+CABLETRON_8390_MEM);
+ dev->mem_end=dev->mem_start+memsize;
+ dev->irq = SLOT2IRQ(ndev->board->slot);
+
+ /* The base address is unreadable if 0x00 has been written to the command register */
+ /* Reset the chip by writing E8390_NODMA+E8390_PAGE0+E8390_STOP just to be sure */
+ i = (void *)dev->base_addr;
+ *i = 0x21;
+
+ printk(KERN_INFO "%s: cabletron: testing board: ", dev->name);
+ printk("%dK memory - ", memsize>>10);
+ i=(void *)dev->mem_start;
+ while(i<(volatile unsigned short *)(dev->mem_start+memsize))
+ {
+ *i=0xAAAA;
+ if(*i!=0xAAAA)
+ goto membad;
+ *i=0x5555;
+ if(*i!=0x5555)
+ goto membad;
+ i+=2; /* Skip a word */
+ }
+ printk("OK\n");
+
+ if(ns8390_probe1(dev, 1, "cabletron", id, -1, ndev)==0)
+ return 0;
}
/* Apple, Farallon, Asante */
- if(id==NS8390_APPLE|| id==NS8390_FARALLON || id==NS8390_ASANTE)
+ if(id==NS8390_APPLE || id==NS8390_FARALLON || id==NS8390_ASANTE)
{
int memsize;
-
- dev->base_addr=(int)(nubus_slot_addr(slot)+APPLE_8390_BASE);
- dev->mem_start=(int)(nubus_slot_addr(slot)+APPLE_8390_MEM);
-
+
+ dev->base_addr=(int)(ndev->board->slot_addr+APPLE_8390_BASE);
+ dev->mem_start=(int)(ndev->board->slot_addr+APPLE_8390_MEM);
+
memsize = apple_8390_mem_probe((void *)dev->mem_start);
-
+
dev->mem_end=dev->mem_start+memsize;
- dev->irq=slot;
- printk("apple/clone: testing board: ");
-
+ dev->irq = SLOT2IRQ(ndev->board->slot);
+
+ switch(id)
+ {
+ case NS8390_FARALLON:
+ printk(KERN_INFO "%s: farallon: testing board: ", dev->name);
+ break;
+ case NS8390_ASANTE:
+ printk(KERN_INFO "%s: asante: testing board: ", dev->name);
+ break;
+ case NS8390_APPLE:
+ default:
+ printk(KERN_INFO "%s: apple/clone: testing board: ", dev->name);
+ break;
+ }
+
printk("%dK memory - ", memsize>>10);
-
+
i=(void *)dev->mem_start;
memset((void *)i,0xAA, memsize);
while(i<(volatile unsigned short *)dev->mem_end)
@@ -295,51 +406,75 @@
i+=2; /* Skip a word */
}
printk("OK\n");
-
- if(id==NS8390_FARALLON)
+
+ switch (id)
{
- if(ns8390_probe1(dev, 1, "farallon", id, -1)==0)
+ case NS8390_FARALLON:
+ if(ns8390_probe1(dev, 1, "farallon", id, -1, ndev)==0)
return 0;
- }
- else
- {
- if(ns8390_probe1(dev, 1, "apple/clone", id, -1)==0)
- return 0;
+ break;
+ case NS8390_ASANTE:
+ if(ns8390_probe1(dev, 1, "asante", id, -1, ndev)==0)
+ return 0;
+ break;
+ case NS8390_APPLE:
+ default:
+ if(ns8390_probe1(dev, 1, "apple/clone", id, -1, ndev)==0)
+ return 0;
+ break;
}
}
/* Interlan */
if(id==NS8390_INTERLAN)
{
/* As apple and asante */
- dev->base_addr=(int)(nubus_slot_addr(slot)+APPLE_8390_BASE);
- dev->mem_start=(int)(nubus_slot_addr(slot)+APPLE_8390_MEM);
+ dev->base_addr=(int)(ndev->board->slot_addr+APPLE_8390_BASE);
+ dev->mem_start=(int)(ndev->board->slot_addr+APPLE_8390_MEM);
dev->mem_end=dev->mem_start+APPLE_MEMSIZE; /* 8K it seems */
- dev->irq=slot;
- if(ns8390_probe1(dev, 1, "interlan", id, -1)==0)
+ dev->irq = SLOT2IRQ(ndev->board->slot);
+ if(ns8390_probe1(dev, 1, "interlan", id, -1, ndev)==0)
return 0;
}
- /* Kinetics */
+ /* Kinetics (Shiva Etherport) */
if(id==NS8390_KINETICS)
{
- dev->base_addr=(int)(nubus_slot_addr(slot)+KINETICS_8390_BASE);
- dev->mem_start=(int)(nubus_slot_addr(slot)+KINETICS_8390_MEM);
+ dev->base_addr=(int)(ndev->board->slot_addr+KINETICS_8390_BASE);
+ dev->mem_start=(int)(ndev->board->slot_addr+KINETICS_8390_MEM);
dev->mem_end=dev->mem_start+KINETICS_MEMSIZE; /* 8K it seems */
- dev->irq=slot;
- if(ns8390_probe1(dev, 0, "kinetics", id, -1)==0)
+ dev->irq = SLOT2IRQ(ndev->board->slot);
+ if(ns8390_probe1(dev, 0, "kinetics", id, -1, ndev)==0)
return 0;
}
- kfree(dev);
+
+ /* We should hopefully not get here */
+ printk(KERN_ERR "Probe unsucessful.\n");
return -ENODEV;
-membad:
- printk("failed.\n");
- kfree(dev);
+
+ membad:
+ printk(KERN_ERR "failed at %p in %p - %p.\n", i,
+ (void *)dev->mem_start, (void *)dev->mem_end);
return -ENODEV;
}
-int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type, int promoff)
+int __init mac8390_ethernet_addr(struct nubus_dev* ndev,
+ unsigned char addr[6])
{
- static unsigned version_printed = 0;
+ struct nubus_dir dir;
+ struct nubus_dirent ent;
+
+ /* Get the functional resource for this device */
+ if (nubus_get_func_dir(ndev, &dir) == -1)
+ return -1;
+ if (nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent) == -1)
+ return -1;
+
+ nubus_get_rsrc_mem(addr, &ent, 6);
+ return 0;
+}
+int __init ns8390_probe1(struct net_device *dev, int word16, char *model_name,
+ int type, int promoff, struct nubus_dev *ndev)
+{
static u32 fwrd4_offsets[16]={
0, 4, 8, 12,
16, 20, 24, 28,
@@ -352,25 +487,19 @@
28, 24, 20, 16,
12, 8, 4, 0
};
+ static u32 fwrd2_offsets[16]={
+ 0, 2, 4, 6,
+ 8, 10, 12, 14,
+ 16, 18, 20, 22,
+ 24, 26, 28, 30
+ };
- unsigned char *prom=((unsigned char *)nubus_slot_addr(dev->irq))+promoff;
+ unsigned char *prom = (unsigned char*) ndev->board->slot_addr + promoff;
- if (ei_debug && version_printed++ == 0)
- printk(version);
-
- /* Snarf the interrupt now. There's no point in waiting since we cannot
- share a slot! and the board will usually be enabled. */
- if (nubus_request_irq(dev->irq, dev, ei_interrupt))
- {
- printk (" unable to get nubus IRQ %d.\n", dev->irq);
- return EAGAIN;
- }
-
/* Allocate dev->priv and fill in 8390 specific dev fields. */
if (ethdev_init(dev))
{
- printk (" unable to get memory for dev->priv.\n");
- nubus_free_irq(dev->irq);
+ printk ("%s: unable to get memory for dev->priv.\n", dev->name);
return -ENOMEM;
}
@@ -378,16 +507,25 @@
ei_status.name = model_name;
ei_status.word16 = word16;
- ei_status.tx_start_page = WD_START_PG;
- ei_status.rx_start_page = WD_START_PG + TX_PAGES;
- dev->rmem_start = dev->mem_start + TX_PAGES*256;
- ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
- dev->rmem_end = dev->mem_end;
+ if (type==NS8390_CABLETRON) {
+ /* Cabletron card puts the RX buffer before the TX buffer */
+ ei_status.tx_start_page = CABLETRON_TX_START_PG;
+ ei_status.rx_start_page = CABLETRON_RX_START_PG;
+ ei_status.stop_page = CABLETRON_RX_STOP_PG;
+ dev->rmem_start = dev->mem_start;
+ dev->rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256;
+ } else {
+ ei_status.tx_start_page = WD_START_PG;
+ ei_status.rx_start_page = WD_START_PG + TX_PAGES;
+ ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
+ dev->rmem_start = dev->mem_start + TX_PAGES*256;
+ dev->rmem_end = dev->mem_end;
+ }
if(promoff==-1) /* Use nubus resources ? */
{
- if(nubus_ethernet_addr(dev->irq /* slot */, dev->dev_addr))
+ if(mac8390_ethernet_addr(ndev, dev->dev_addr))
{
printk("mac_ns8390: MAC address not in resources!\n");
return -ENODEV;
@@ -400,7 +538,7 @@
/* These should go in the end I hope */
if(type==NS8390_DAYNA)
x=2;
- if(type==NS8390_INTERLAN)
+ if(type==NS8390_INTERLAN || type==NS8390_KINETICS)
x=4;
while(i<6)
{
@@ -412,12 +550,24 @@
}
}
- printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
- model_name, dev->irq, dev->mem_start, dev->mem_end-1);
+ printk(KERN_INFO "%s: %s in slot %X (type %s)\n",
+ dev->name, ndev->board->name, ndev->board->slot, model_name);
+ printk(KERN_INFO "MAC ");
+ {
+ int i;
+ for (i = 0; i < 6; i++) {
+ printk("%2.2x", dev->dev_addr[i]);
+ if (i < 5)
+ printk(":");
+ }
+ }
+ printk(" IRQ %d, shared memory at %#lx-%#lx.\n",
+ dev->irq, dev->mem_start, dev->mem_end-1);
switch(type)
{
case NS8390_DAYNA: /* Dayna card */
+ case NS8390_KINETICS: /* Kinetics -- 8 bit config, but 16 bit mem */
/* 16 bit, 4 word offsets */
ei_status.reset_8390 = &ns8390_no_reset;
ei_status.block_input = &dayna_block_input;
@@ -425,6 +575,15 @@
ei_status.get_8390_hdr = &dayna_get_8390_hdr;
ei_status.reg_offset = fwrd4_offsets;
break;
+ case NS8390_CABLETRON: /* Cabletron */
+ /* 16 bit card, register map is short forward */
+ ei_status.reset_8390 = &ns8390_no_reset;
+ /* Ctron card won't accept 32bit values read or written to it */
+ 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 = fwrd2_offsets;
+ break;
case NS8390_FARALLON:
case NS8390_APPLE: /* Apple/Asante/Farallon */
/* 16 bit card, register map is reversed */
@@ -450,6 +609,8 @@
ei_status.get_8390_hdr = &sane_get_8390_hdr;
ei_status.reg_offset = back4_offsets;
break;
+#if 0 /* i think this suffered code rot. my kinetics card has much
+ * different settings. -- CSA [22-May-1999] */
case NS8390_KINETICS: /* Kinetics */
/* 8bit card, map is forward */
ei_status.reset_8390 = &ns8390_no_reset;
@@ -458,6 +619,7 @@
ei_status.get_8390_hdr = &sane_get_8390_hdr;
ei_status.reg_offset = back4_offsets;
break;
+#endif
default:
panic("Detected a card I can't drive - whoops\n");
}
@@ -472,6 +634,19 @@
static int ns8390_open(struct net_device *dev)
{
ei_open(dev);
+
+ /* At least on my card (a Focus Enhancements PDS card) I start */
+ /* getting interrupts right away, so the driver needs to be */
+ /* completely initialized before enabling the interrupt. */
+ /* - funaho@jurai.org (1999-05-17) */
+
+ /* Non-slow interrupt, works around issues with the SONIC driver */
+ 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;
+ }
+
MOD_INC_USE_COUNT;
return 0;
}
@@ -489,24 +664,19 @@
{
if (ei_debug > 1)
printk("%s: Shutting down ethercard.\n", dev->name);
+ free_irq(dev->irq, dev);
ei_close(dev);
MOD_DEC_USE_COUNT;
return 0;
}
-struct nubus_device_specifier nubus_8390={
- ns8390_probe,
- NULL
-};
-
-
/*
* Interlan Specific Code Starts Here
*/
static void interlan_reset(struct net_device *dev)
{
- unsigned char *target=nubus_slot_addr(dev->irq);
+ 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;
@@ -531,16 +701,23 @@
The only complications are that the ring buffer wraps.
*/
-static void dayna_cpu_memcpy(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)
{
volatile unsigned short *ptr;
unsigned short *target=to;
from<<=1; /* word, skip overhead */
ptr=(unsigned short *)(dev->mem_start+from);
+ /*
+ * Leading byte?
+ */
+ if (from&2) {
+ *((char *)target)++ = *(((char *)ptr++)-1);
+ count--;
+ }
while(count>=2)
{
*target++=*ptr++; /* Copy and */
- ptr++; /* Cruft and */
+ ptr++; /* skip cruft */
count-=2;
}
/*
@@ -554,16 +731,24 @@
}
}
-static void cpu_dayna_memcpy(struct net_device *dev, int to, const void *from, int count)
+static void dayna_memcpy_tocard(struct net_device *dev, int to, const void *from, int count)
{
volatile unsigned short *ptr;
const unsigned short *src=from;
to<<=1; /* word, skip overhead */
ptr=(unsigned short *)(dev->mem_start+to);
+ /*
+ * Leading byte?
+ */
+ if (to&2) { /* avoid a byte write (stomps on other data) */
+ ptr[-1] = (ptr[-1]&0xFF00)|*((unsigned char *)src)++;
+ ptr++;
+ count--;
+ }
while(count>=2)
{
*ptr++=*src++; /* Copy and */
- ptr++; /* Cruft and */
+ ptr++; /* skip cruft */
count-=2;
}
/*
@@ -573,14 +758,15 @@
{
/* Big endian */
unsigned short v=*src;
- *((char *)ptr)=v>>8;
+ /* card doesn't like byte writes */
+ *ptr=(*ptr&0x00FF)|(v&0xFF00);
}
}
static void dayna_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;
- dayna_cpu_memcpy(dev, (void *)hdr, hdr_start, 4);
+ dayna_memcpy_fromcard(dev, (void *)hdr, hdr_start, 4);
/* Register endianism - fix here rather than 8390.c */
hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
}
@@ -599,14 +785,14 @@
{
/* We must wrap the input move. */
int semi_count = dev->rmem_end - xfer_start;
- dayna_cpu_memcpy(dev, skb->data, xfer_base, semi_count);
+ dayna_memcpy_fromcard(dev, skb->data, xfer_base, semi_count);
count -= semi_count;
- dayna_cpu_memcpy(dev, skb->data + semi_count,
+ dayna_memcpy_fromcard(dev, skb->data + semi_count,
dev->rmem_start - dev->mem_start, count);
}
else
{
- dayna_cpu_memcpy(dev, skb->data, xfer_base, count);
+ dayna_memcpy_fromcard(dev, skb->data, xfer_base, count);
}
}
@@ -615,7 +801,7 @@
{
long shmem = (start_page - WD_START_PG)<<8;
- cpu_dayna_memcpy(dev, shmem, buf, count);
+ dayna_memcpy_tocard(dev, shmem, buf, count);
}
/*
@@ -739,6 +925,7 @@
* Local variables:
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c daynaport.c"
* version-control: t
+ * c-basic-offset: 4
* tab-width: 4
* kept-new-versions: 5
* End:
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)