summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-18 22:06:10 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-18 22:06:10 +0000
commitaba4e552a2f2c1492441acbccedd8e0a4c53f916 (patch)
tree23921efb2b4af590160f034a89ff3da2ecca6e47 /drivers/net
parent9e17e1aa1cf1cb497d2f67147a51831888affcf3 (diff)
Merge with Linux 2.3.43.
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/Makefile4
-rw-r--r--drivers/net/Space.c21
-rw-r--r--drivers/net/cs89x0.h8
-rw-r--r--drivers/net/daynaport.c451
-rw-r--r--drivers/net/irda/Config.in10
-rw-r--r--drivers/net/irda/Makefile12
-rw-r--r--drivers/net/irda/airport.c358
-rw-r--r--drivers/net/irda/irport.c61
-rw-r--r--drivers/net/irda/irtty.c10
-rw-r--r--drivers/net/irda/nsc-ircc.c (renamed from drivers/net/irda/nsc_fir.c)1018
-rw-r--r--drivers/net/irda/smc-ircc.c699
-rw-r--r--drivers/net/irda/toshoboe.c46
-rw-r--r--drivers/net/irda/w83977af_ir.c51
-rw-r--r--drivers/net/mac89x0.c678
-rw-r--r--drivers/net/macmace.c825
-rw-r--r--drivers/net/macsonic.c834
-rw-r--r--drivers/net/sun3lance.c21
-rw-r--r--drivers/net/sunbmac.c2
-rw-r--r--drivers/net/sunhme.c2
-rw-r--r--drivers/net/sunlance.c2
-rw-r--r--drivers/net/sunqe.c2
21 files changed, 3492 insertions, 1623 deletions
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 03864c4ba..232075634 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -115,7 +115,7 @@ obj-$(CONFIG_NET) += Space.o setup.o net_init.o loopback.o
obj-$(CONFIG_SEEQ8005) += seeq8005.o
obj-$(CONFIG_ETHERTAP) += ethertap.o
obj-$(CONFIG_NET_SB1000) += sb1000.o
-obj-$(CONFIG_DAYNAPORT) += daynaport.o 8390.o
+obj-$(CONFIG_MAC8390) += daynaport.o 8390.o
obj-$(CONFIG_APNE) += apne.o 8390.o
obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
obj-$(CONFIG_SHAPER) += shaper.o
@@ -248,6 +248,8 @@ obj-$(CONFIG_IPDDP) += ipddp.o
obj-$(CONFIG_RCPCI) += rcpci.o
obj-$(CONFIG_MACE) += mace.o
obj-$(CONFIG_MACSONIC) += macsonic.o
+obj-$(CONFIG_MACMACE) += macmace.o
+obj-$(CONFIG_MAC89x0) += mac89x0.o
obj-$(CONFIG_BMAC) += bmac.o
obj-$(CONFIG_NCR885E) += ncr885e.o
obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index dc18256ce..52c3a23d0 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -106,7 +106,13 @@ extern int dec_lance_probe(struct net_device *);
extern int mvme147lance_probe(struct net_device *dev);
extern int tc515_probe(struct net_device *dev);
extern int lance_probe(struct net_device *dev);
-extern int mac_onboard_sonic_probe(struct net_device *dev);
+extern int mace68k_probe(struct net_device *dev);
+extern int macsonic_probe(struct net_device *dev);
+extern int mac8390_probe(struct net_device *dev);
+extern int mac89x0_probe(struct net_device *dev);
+
+ /* Gigabit Ethernet adapters */
+ extern int yellowfin_probe(struct net_device *dev);
/* Detachable devices ("pocket adaptors") */
extern int atp_init(struct net_device *);
@@ -356,8 +362,17 @@ struct devprobe m68k_probes[] __initdata = {
#ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */
{mvme147lance_probe, 0},
#endif
-#ifdef CONFIG_MACSONIC /* Mac 68k Quadra builtin Ethernet */
- {mac_onboard_sonic_probe, 0},
+#ifdef CONFIG_MACMACE /* Mac 68k Quadra AV builtin Ethernet */
+ {mace68k_probe, 0},
+#endif
+#ifdef CONFIG_MACSONIC /* Mac SONIC-based Ethernet of all sorts */
+ {macsonic_probe, 0},
+#endif
+#ifdef CONFIG_MAC8390 /* NuBus NS8390-based cards */
+ {mac8390_probe, 0},
+#endif
+#ifdef CONFIG_MAC89x0
+ {mac89x0_probe, 0},
#endif
{NULL, 0},
};
diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h
index 42776088f..7e78805af 100644
--- a/drivers/net/cs89x0.h
+++ b/drivers/net/cs89x0.h
@@ -14,6 +14,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/config.h>
+
#define PP_ChipID 0x0000 /* offset 0h -> Corp -ID */
/* offset 2h -> Model/Product Number */
/* offset 3h -> Chip Revision Number */
@@ -77,6 +79,12 @@
#define ADD_MASK 0x3000 /* Mask it use of the ADD_PORT register */
#define ADD_SIG 0x3000 /* Expected ID signature */
+/* On Macs, we only need use the ISA I/O stuff until we do MEMORY_ON */
+#ifdef CONFIG_MAC
+#define LCSLOTBASE 0xfee00000
+#define MMIOBASE 0x40000
+#endif
+
#define CHIP_EISA_ID_SIG 0x630E /* Product ID Code for Crystal Chip (CS8900 spec 4.3) */
#ifdef IBMEIPKT
diff --git a/drivers/net/daynaport.c b/drivers/net/daynaport.c
index 02ebff8b6..724369bb8 100644
--- a/drivers/net/daynaport.c
+++ b/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 @@ static const char *version =
#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_input(struct net_device *dev, int count,
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_input(struct net_device *dev, int count,
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 @@ static void slow_sane_block_output(struct net_device *dev, int count,
#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 @@ static void slow_sane_block_output(struct net_device *dev, int count,
#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 @@ static int test_8390(volatile char *ptr, int scale)
* 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
+enum mac8390_type {
+ NS8390_DAYNA,
+ NS8390_INTERLAN,
+ NS8390_KINETICS,
+ NS8390_APPLE,
+ NS8390_FARALLON,
+ NS8390_ASANTE,
+ NS8390_CABLETRON
+};
-int ns8390_ident(struct nubus_type *nb)
+int __init ns8390_ident(struct nubus_dev* ndev)
{
- /* 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;
-
+ /* 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 @@ int ns8390_ident(struct nubus_type *nb)
* 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 @@ int apple_8390_mem_probe(volatile unsigned short *p)
/*
* 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;
+
+ /* 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;
+ }
- 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);
+ /* 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 @@ int ns8390_probe(struct nubus_device_specifier *d, int slot, struct nubus_type *
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 @@ int ns8390_probe(struct nubus_device_specifier *d, int slot, struct nubus_type *
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 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
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 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
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 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
/* 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 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
}
}
- 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 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
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 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
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 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
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 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
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 @@ static int ns8390_close_card(struct net_device *dev)
{
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 @@ static void interlan_reset(struct net_device *dev)
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 dayna_cpu_memcpy(struct net_device *dev, void *to, int from, int cou
}
}
-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 @@ static void cpu_dayna_memcpy(struct net_device *dev, int to, const void *from, i
{
/* 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 @@ static void dayna_block_input(struct net_device *dev, int count, struct sk_buff
{
/* 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 @@ static void dayna_block_output(struct net_device *dev, int count, const unsigned
{
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 @@ static void slow_sane_block_output(struct net_device *dev, int count, const unsi
* 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:
diff --git a/drivers/net/irda/Config.in b/drivers/net/irda/Config.in
index da1df253c..da0b5f4be 100644
--- a/drivers/net/irda/Config.in
+++ b/drivers/net/irda/Config.in
@@ -6,10 +6,12 @@ dep_tristate 'IrTTY (uses Linux serial driver)' CONFIG_IRTTY_SIR $CONFIG_IRDA
dep_tristate 'IrPORT (IrDA serial driver)' CONFIG_IRPORT_SIR $CONFIG_IRDA
comment 'FIR device drivers'
-dep_tristate 'NSC PC87108/PC97338' CONFIG_NSC_FIR $CONFIG_IRDA
+dep_tristate 'NSC PC87108/PC87338' CONFIG_NSC_FIR $CONFIG_IRDA
dep_tristate 'Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
dep_tristate 'Toshiba Type-O IR Port' CONFIG_TOSHIBA_FIR $CONFIG_IRDA
-dep_tristate 'SMC IrCC' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA
+if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+dep_tristate 'SMC IrCC (Experimental)' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA
+fi
comment 'Dongle support'
bool 'Serial dongle support' CONFIG_DONGLE
@@ -19,9 +21,7 @@ if [ "$CONFIG_DONGLE" != "n" ]; then
dep_tristate ' Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRDA
dep_tristate ' Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRDA
dep_tristate ' Parallax LiteLink dongle' CONFIG_LITELINK_DONGLE $CONFIG_IRDA
- dep_tristate ' Adaptec Airport 1000/2000 dongle' CONFIG_AIRPORT_DONGLE $CONFIG_IRDA
- dep_tristate ' Old Belkin dongle' CONFIG_OLD_BELKIN_DONGLE $CONFIG_IRDA
-
+ dep_tristate ' Old Belkin dongle' CONFIG_OLD_BELKIN_DONGLE $CONFIG_IRDA
fi
endmenu
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index bf5628ebd..291a27f05 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -29,10 +29,10 @@ else
endif
ifeq ($(CONFIG_NSC_FIR),y)
-L_OBJS += nsc_fir.o
+L_OBJS += nsc-ircc.o
else
ifeq ($(CONFIG_NSC_FIR),m)
- M_OBJS += nsc_fir.o
+ M_OBJS += nsc-ircc.o
endif
endif
@@ -118,14 +118,6 @@ else
endif
endif
-ifeq ($(CONFIG_AIRPORT_DONGLE),y)
-L_OBJS += airport.o
-else
- ifeq ($(CONFIG_AIRPORT_DONGLE),m)
- M_OBJS += airport.o
- endif
-endif
-
ifeq ($(CONFIG_OLD_BELKIN_DONGLE),y)
L_OBJS += old_belkin.o
else
diff --git a/drivers/net/irda/airport.c b/drivers/net/irda/airport.c
deleted file mode 100644
index b68378189..000000000
--- a/drivers/net/irda/airport.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*********************************************************************
- *
- * Filename: airport.c
- * Version: 0.2
- * Description: Implementation for the Adaptec Airport 1000 and 2000
- * dongles
- * Status: Experimental.
- * Author: Fons Botman <budely@tref.nl>
- * Created at: Wed May 19 23:14:34 CEST 1999
- * Based on: actisys.c by Dag Brattli <dagb@cs.uit.no>
- *
- * Copyright (c) 1998-1999 Fons Botman, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * Neither Fons Botman nor anyone else admit liability nor
- * provide warranty for any of this software. This material is
- * provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/tty.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-
-#include <net/irda/irda.h>
-#include <net/irda/irmod.h>
-#include <net/irda/irda_device.h>
-
-static int airport_reset_wrapper(struct irda_task *task);
-static void airport_open(dongle_t *self, struct qos_info *qos);
-static void airport_close(dongle_t *self);
-static int airport_change_speed_wrapper(struct irda_task *task);
-
-static struct dongle_reg dongle = {
- Q_NULL,
- IRDA_AIRPORT_DONGLE,
- airport_open,
- airport_close,
- airport_reset_wrapper,
- airport_change_speed_wrapper,
-};
-
-int __init airport_init(void)
-{
- int ret;
-
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
- ret = irda_device_register_dongle(&dongle);
- if (ret < 0)
- return ret;
- return 0;
-}
-
-void airport_cleanup(void)
-{
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
- irda_device_unregister_dongle(&dongle);
-}
-
-static void airport_open(dongle_t *self, struct qos_info *qos)
-{
- qos->baud_rate.bits &=
- IR_2400|IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
- /* May need 1ms */
- qos->min_turn_time.bits = 0x07;
-
- MOD_INC_USE_COUNT;
-}
-
-static void airport_close(dongle_t *self)
-{
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
- /* Power off dongle */
- self->set_dtr_rts(self->dev, FALSE, FALSE);
-
- MOD_DEC_USE_COUNT;
-}
-
-static void airport_set_command_mode(dongle_t *self)
-{
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
- self->set_dtr_rts(self->dev, FALSE, TRUE);
-}
-
-static void airport_set_normal_mode(dongle_t *self)
-{
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
- self->set_dtr_rts(self->dev, TRUE, TRUE);
-}
-
-void airport_write_char(dongle_t *self, unsigned char c)
-{
- int actual;
- IRDA_DEBUG(2, __FUNCTION__ "(,0x%x)\n", c & 0xff);
- actual = self->write(self->dev, &c, 1);
- ASSERT(actual == 1, return;);
-}
-
-#define JIFFIES_TO_MSECS(j) ((j)*1000/HZ)
-
-static int airport_waitfor_char(dongle_t *self, unsigned char c)
-{
- __u8 buf[100];
- int i, found = FALSE;
- int before;
- int len;
-
- IRDA_DEBUG(2, __FUNCTION__ "(,0x%x)\n", c);
-
- /* Sleep approx. 10 ms */
- before = jiffies;
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(20));
- IRDA_DEBUG(4, __FUNCTION__ " waited %ldms\n",
- JIFFIES_TO_MSECS(jiffies - before));
-
- len = self->read(self->dev, buf, 100);
-
- for (i = 0; !found && i < len; i++ ) {
- /* IRDA_DEBUG(6, __FUNCTION__ " 0x02x\n", idev->rx_buff.data[i]); */
- found = c == buf[i];
- }
-
- IRDA_DEBUG(2, __FUNCTION__ " returns %s\n", (found ? "true" : "false"));
- return found;
-}
-
-static int airport_check_command_mode(dongle_t *self)
-{
- int i;
- int found = FALSE;
-
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(20));
- airport_set_command_mode(self);
-
- /* Loop until the time expires (200ms) or we get the magic char. */
-
- for ( i = 0 ; i < 25 ; i++ ) {
- airport_write_char(self, 0xff);
- if (airport_waitfor_char(self, 0xc3)) {
- found = TRUE;
- break;
- }
- }
-
- if (found) {
- IRDA_DEBUG(2, __FUNCTION__ " OK. (%d)\n", i);
- } else {
- IRDA_DEBUG(0, __FUNCTION__ " FAILED!\n");
- }
- return found;
-}
-
-static int airport_write_register(dongle_t *self, unsigned char reg)
-{
- int ok = FALSE;
- int i;
-
- IRDA_DEBUG(4, __FUNCTION__ "(,0x%x)\n", reg);
- airport_check_command_mode(self);
-
- for ( i = 0 ; i < 6 ; i++ ) {
- airport_write_char(self, reg);
- if (!airport_waitfor_char(self, reg))
- continue;
-
- /* Now read it back */
- airport_write_char(self, (reg << 4) | 0x0f);
- if (airport_waitfor_char(self, reg)) {
- ok = TRUE;
- break;
- }
- }
-
- airport_set_normal_mode(self);
- if (ok) {
- IRDA_DEBUG(4, __FUNCTION__ "(,0x%x) returns OK\n", reg);
- } else {
- IRDA_DEBUG(0, __FUNCTION__ "(,0x%x) returns False!\n", reg);
- }
- return ok;
-}
-
-
-/*
- * Function airport_change_speed (self, speed)
- *
- * Change speed of the Airport type IrDA dongles.
- */
-static void airport_change_speed(dongle_t *self, __u32 speed)
-{
- __u32 current_baudrate;
- int baudcode;
-
- IRDA_DEBUG(4, __FUNCTION__ "(,%d)\n", speed);
-
- ASSERT(self != NULL, return;);
-
- /* Find the correct baudrate code for the required baudrate */
- switch (speed) {
- case 2400: baudcode = 0x10; break;
- case 4800: baudcode = 0x20; break;
- case 9600: baudcode = 0x30; break;
- case 19200: baudcode = 0x40; break;
- case 38400: baudcode = 0x50; break;
- case 57600: baudcode = 0x60; break;
- case 115200: baudcode = 0x70; break;
- default:
- IRDA_DEBUG(0, __FUNCTION__ " bad baud rate: %d\n", speed);
- return;
- }
-
- current_baudrate = self->speed;
- IRDA_DEBUG(4, __FUNCTION__ " current baudrate: %d\n", current_baudrate);
-
- self->set_mode(self->dev, IRDA_RAW);
-
- /* Set the new speed in both registers */
- if (airport_write_register(self, baudcode)) {
- if (airport_write_register(self, baudcode|0x01)) {
- /* ok */
- } else {
- IRDA_DEBUG(0, __FUNCTION__
- " Cannot set new speed in second register\n");
- }
- } else {
- IRDA_DEBUG(0, __FUNCTION__
- " Cannot set new speed in first register\n");
- }
-
- self->set_mode(self->dev, IRDA_IRLAP);
-
- /* How do I signal an error in these functions? */
-
- IRDA_DEBUG(4, __FUNCTION__ " returning\n");
-}
-
-int airport_change_speed_wrapper(struct irda_task *task)
-{
- dongle_t *self = (dongle_t *) task->instance;
- __u32 speed = (__u32) task->param;
-
- irda_execute_as_process(self, (TODO_CALLBACK) airport_change_speed,
- speed);
-
- irda_task_next_state(task, IRDA_TASK_DONE);
-
- return 0;
-}
-
-/*
- * Function airport_reset (self)
- *
- * Reset the Airport type dongle. Warning, this function must only be
- * called with a process context!
- *
- */
-static void airport_reset(dongle_t *self)
-{
- int ok;
-
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
- ASSERT(self != NULL, return;);
-
- self->set_mode(self->dev, IRDA_RAW);
-
- airport_set_normal_mode(self);
-
- /* Sleep 2000 ms */
- IRDA_DEBUG(2, __FUNCTION__ " waiting for powerup\n");
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(2000));
- IRDA_DEBUG(2, __FUNCTION__ " finished waiting for powerup\n");
-
- /* set dongle speed to 9600 */
- ok = TRUE;
-
- if (ok)
- ok = airport_write_register(self, 0x30);
- if (!ok)
- MESSAGE(__FUNCTION__ "() dongle not connected?\n");
- if (ok)
- ok = airport_write_register(self, 0x31);
-
- if (ok)
- ok = airport_write_register(self, 0x02);
- if (ok)
- ok = airport_write_register(self, 0x03);
-
- if (ok) {
- ok = airport_check_command_mode(self);
-
- if (ok) {
- airport_write_char(self, 0x04);
- ok = airport_waitfor_char(self, 0x04);
- }
- airport_set_normal_mode(self);
- }
-
- self->set_mode(self->dev, IRDA_IRLAP);
-
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(20));
- IRDA_DEBUG(4, __FUNCTION__ " waited 20ms\n");
-
- self->speed = 9600;
- if (!ok)
- MESSAGE(__FUNCTION__ "() failed.\n");
- IRDA_DEBUG(2, __FUNCTION__ " returning.\n");
-}
-
-int airport_reset_wrapper(struct irda_task *task)
-{
- dongle_t *self = (dongle_t *) task->instance;
-
- irda_execute_as_process(self, (TODO_CALLBACK) airport_reset, 0);
-
- irda_task_next_state(task, IRDA_TASK_DONE);
-
- return 0;
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Fons Botman <budely@tref.nl>");
-MODULE_DESCRIPTION("Adaptec Airport 1000 and 2000 dongle driver");
-
-/*
- * Function init_module (void)
- *
- * Initialize Airport module
- *
- */
-int init_module(void)
-{
- return airport_init();
-}
-
-/*
- * Function cleanup_module (void)
- *
- * Cleanup Airport module
- *
- */
-void cleanup_module(void)
-{
- airport_cleanup();
-}
-
-#endif
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index 352dddecc..d8832292a 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 3 13:49:59 1997
- * Modified at: Wed Jan 5 13:59:38 2000
+ * Modified at: Fri Jan 28 20:22:38 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: serial.c by Linus Torvalds
*
@@ -161,20 +161,19 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
self->index = i;
/* Initialize IO */
- self->io.iobase = iobase;
+ self->io.sir_base = iobase;
+ self->io.sir_ext = IO_EXTENT;
self->io.irq = irq;
- self->io.io_ext = IO_EXTENT;
self->io.fifo_size = 16;
/* Lock the port that we need */
- ret = check_region(self->io.iobase, self->io.io_ext);
+ ret = check_region(self->io.sir_base, self->io.sir_ext);
if (ret < 0) {
IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- self->io.iobase);
- /* irport_cleanup(self->self); */
+ self->io.sir_base);
return NULL;
}
- request_region(self->io.iobase, self->io.io_ext, driver_name);
+ request_region(self->io.sir_base, self->io.sir_ext, driver_name);
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&self->qos);
@@ -218,7 +217,6 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
return NULL;
}
-
self->netdev = dev;
/* May be overridden by piggyback drivers */
@@ -268,19 +266,19 @@ int irport_close(struct irport_cb *self)
/* Release the IO-port that this driver is using */
IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n",
- self->io.iobase);
- release_region(self->io.iobase, self->io.io_ext);
+ self->io.sir_base);
+ release_region(self->io.sir_base, self->io.sir_ext);
if (self->tx_buff.head)
kfree(self->tx_buff.head);
if (self->rx_buff.head)
kfree(self->rx_buff.head);
-
+
/* Remove ourselves */
dev_self[self->index] = NULL;
kfree(self);
-
+
return 0;
}
@@ -289,7 +287,7 @@ void irport_start(struct irport_cb *self)
unsigned long flags;
int iobase;
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
spin_lock_irqsave(&self->lock, flags);
@@ -310,7 +308,7 @@ void irport_stop(struct irport_cb *self)
unsigned long flags;
int iobase;
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
spin_lock_irqsave(&self->lock, flags);
@@ -355,7 +353,7 @@ void irport_change_speed(void *priv, __u32 speed)
ASSERT(self != NULL, return;);
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
/* Update accounting for new speed */
self->io.speed = speed;
@@ -431,7 +429,7 @@ int __irport_change_speed(struct irda_task *task)
break;
case IRDA_TASK_CHILD_INIT:
/* Go to default speed */
- irport_change_speed(self, 9600);
+ self->change_speed(self->priv, 9600);
/* Change speed of dongle */
if (irda_task_execute(self->dongle,
@@ -454,7 +452,7 @@ int __irport_change_speed(struct irda_task *task)
break;
case IRDA_TASK_CHILD_DONE:
/* Finally we are ready to change the speed */
- irport_change_speed(self, speed);
+ self->change_speed(self->priv, speed);
irda_task_next_state(task, IRDA_TASK_DONE);
break;
@@ -484,7 +482,7 @@ static void irport_write_wakeup(struct irport_cb *self)
IRDA_DEBUG(4, __FUNCTION__ "()\n");
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
/* Finished with frame? */
if (self->tx_buff.len > 0) {
@@ -598,7 +596,6 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct irport_cb *self;
unsigned long flags;
- int actual = 0;
int iobase;
__u32 speed;
@@ -607,7 +604,7 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self = (struct irport_cb *) dev->priv;
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
/* Lock transmit buffer */
if (irda_lock((void *) &dev->tbusy) == FALSE) {
@@ -617,7 +614,7 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
WARNING("%s: transmit timed out\n", dev->name);
irport_start(self);
- irport_change_speed(self, self->io.speed );
+ self->change_speed(self->priv, self->io.speed);
dev->trans_start = jiffies;
}
@@ -635,8 +632,7 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
self->tx_buff.truesize);
- self->tx_buff.data += actual;
- self->tx_buff.len -= actual;
+ self->stats.tx_bytes += self->tx_buff.len;
/* Turn on transmit finished interrupt. Will fire immediately! */
outb(UART_IER_THRI, iobase+UART_IER);
@@ -661,7 +657,7 @@ static void irport_receive(struct irport_cb *self)
ASSERT(self != NULL, return;);
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
/*
* Receive all characters in Rx FIFO, unwrap and unstuff them.
@@ -702,15 +698,16 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
dev->interrupt = 1;
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
iir = inb(iobase+UART_IIR) & UART_IIR_ID;
while (iir) {
/* Clear interrupt */
lsr = inb(iobase+UART_LSR);
- IRDA_DEBUG(4, __FUNCTION__ "(), iir=%02x, lsr=%02x, iobase=%#x\n",
- iir, lsr, iobase);
+ IRDA_DEBUG(4, __FUNCTION__
+ "(), iir=%02x, lsr=%02x, iobase=%#x\n",
+ iir, lsr, iobase);
switch (iir) {
case UART_IIR_RLSI:
@@ -765,7 +762,7 @@ int irport_net_open(struct net_device *dev)
ASSERT(dev != NULL, return -1;);
self = (struct irport_cb *) dev->priv;
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
if (request_irq(self->io.irq, self->interrupt, 0, dev->name,
(void *) dev))
@@ -809,7 +806,7 @@ int irport_net_close(struct net_device *dev)
ASSERT(self != NULL, return -1;);
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
/* Stop device */
dev->tbusy = 1;
@@ -840,7 +837,7 @@ void irport_wait_until_sent(struct irport_cb *self)
{
int iobase;
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
/* Wait until Tx FIFO is empty */
while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
@@ -875,7 +872,7 @@ static int irport_set_dtr_rts(struct net_device *dev, int dtr, int rts)
ASSERT(self != NULL, return -1;);
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
if (dtr)
dtr = UART_MCR_DTR;
@@ -895,7 +892,7 @@ static int irport_raw_write(struct net_device *dev, __u8 *buf, int len)
ASSERT(self != NULL, return -1;);
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
/* Tx FIFO should be empty! */
if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c
index 2ec4eba14..370a9c7fe 100644
--- a/drivers/net/irda/irtty.c
+++ b/drivers/net/irda/irtty.c
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Dec 9 21:18:38 1997
- * Modified at: Wed Jan 5 14:00:13 2000
+ * Modified at: Fri Jan 14 21:02:27 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
* Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
@@ -233,6 +233,8 @@ static int irtty_open(struct tty_struct *tty)
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
return -ENOMEM;
}
+ /* dev_alloc doesn't clear the struct */
+ memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
dev->priv = (void *) self;
self->netdev = dev;
@@ -654,6 +656,7 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
dev->trans_start = jiffies;
+ self->stats.tx_bytes += self->tx_buff.len;
if (self->tty->driver.write)
actual = self->tty->driver.write(self->tty, 0,
@@ -663,9 +666,6 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self->tx_buff.data += actual;
self->tx_buff.len -= actual;
- self->stats.tx_packets++;
- self->stats.tx_bytes += self->tx_buff.len;
-
dev_kfree_skb(skb);
return 0;
@@ -709,6 +709,8 @@ static void irtty_write_wakeup(struct tty_struct *tty)
self->tx_buff.data += actual;
self->tx_buff.len -= actual;
+
+ self->stats.tx_packets++;
} else {
/*
* Now serial buffer is almost free & we can start
diff --git a/drivers/net/irda/nsc_fir.c b/drivers/net/irda/nsc-ircc.c
index affd1d8fa..e8aaa8459 100644
--- a/drivers/net/irda/nsc_fir.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -1,12 +1,12 @@
/*********************************************************************
*
- * Filename: nsc_fir.c
+ * Filename: nsc-ircc.c
* Version: 1.0
* Description: Driver for the NSC PC'108 and PC'338 IrDA chipsets
* Status: Stable.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Nov 7 21:43:15 1998
- * Modified at: Wed Jan 5 13:59:21 2000
+ * Modified at: Fri Jan 28 12:10:10 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
@@ -41,8 +41,9 @@
*
********************************************************************/
-#include <linux/module.h>
#include <linux/config.h>
+#include <linux/module.h>
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/skbuff.h>
@@ -67,29 +68,38 @@
#include <net/irda/irlap_frame.h>
#include <net/irda/irda_device.h>
-#include <net/irda/nsc_fir.h>
+#include <net/irda/nsc-ircc.h>
#define CHIP_IO_EXTENT 8
#define BROKEN_DONGLE_ID
-/*
- * Define if you have multiple NSC IrDA controllers in your machine. Not
- * enabled by default since some single chips detects at multiple addresses
- */
-#undef CONFIG_NSC_FIR_MULTIPLE
-
-static char *driver_name = "nsc_fir";
+static char *driver_name = "nsc-ircc";
/* Module parameters */
static int qos_mtt_bits = 0x07; /* 1 ms or more */
static int dongle_id = 0;
-static unsigned int io[] = { 0x2f8, 0x2f8, 0x2f8, 0x2f8, 0x2f8 };
-static unsigned int io2[] = { 0x150, 0x398, 0xea, 0x15c, 0x2e };
-static unsigned int irq[] = { 3, 3, 3, 3, 3 };
-static unsigned int dma[] = { 0, 0, 0, 0, 3 };
+/* Use BIOS settions by default, but user may supply module parameters */
+static unsigned int io[] = { ~0, ~0, ~0, ~0 };
+static unsigned int irq[] = { 0, 0, 0, 0, 0 };
+static unsigned int dma[] = { 0, 0, 0, 0, 0 };
+
+static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info);
+static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info);
+static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info);
+static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info);
+
+/* These are the known NSC chips */
+static nsc_chip_t chips[] = {
+ { "PC87108", { 0x150, 0x398, 0xea }, 0x05, 0x10, 0xf0,
+ nsc_ircc_probe_108, nsc_ircc_init_108 },
+ { "PC87338", { 0x398, 0x15c, 0x2e }, 0x08, 0xb0, 0xf0,
+ nsc_ircc_probe_338, nsc_ircc_init_338 },
+ { NULL }
+};
-static struct nsc_fir_cb *dev_self[] = { NULL, NULL, NULL, NULL, NULL };
+/* Max 4 instances for now */
+static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL };
static char *dongle_types[] = {
"Differential serial interface",
@@ -111,143 +121,182 @@ static char *dongle_types[] = {
};
/* Some prototypes */
-static int nsc_fir_open(int i, unsigned int iobase, unsigned int board_addr,
- unsigned int irq, unsigned int dma);
+static int nsc_ircc_open(int i, chipio_t *info);
#ifdef MODULE
-static int nsc_fir_close(struct nsc_fir_cb *self);
+static int nsc_ircc_close(struct nsc_ircc_cb *self);
#endif /* MODULE */
-static int nsc_fir_probe(int iobase, int board_addr, int irq, int dma);
-static void nsc_fir_pio_receive(struct nsc_fir_cb *self);
-static int nsc_fir_dma_receive(struct nsc_fir_cb *self);
-static int nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase);
-static int nsc_fir_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev);
-static int nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev);
-static int nsc_fir_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
-static void nsc_fir_dma_xmit(struct nsc_fir_cb *self, int iobase);
-static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 baud);
-static void nsc_fir_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int nsc_fir_is_receiving(struct nsc_fir_cb *self);
-static int nsc_fir_read_dongle_id (int iobase);
-static void nsc_fir_init_dongle_interface (int iobase, int dongle_id);
-
-static int nsc_fir_net_init(struct net_device *dev);
-static int nsc_fir_net_open(struct net_device *dev);
-static int nsc_fir_net_close(struct net_device *dev);
-static int nsc_fir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static struct net_device_stats *nsc_fir_net_get_stats(struct net_device *dev);
+static int nsc_ircc_setup(chipio_t *info);
+static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self);
+static int nsc_ircc_dma_receive(struct nsc_ircc_cb *self);
+static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase);
+static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev);
+static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev);
+static int nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
+static void nsc_ircc_dma_xmit(struct nsc_ircc_cb *self, int iobase);
+static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 baud);
+static void nsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static int nsc_ircc_is_receiving(struct nsc_ircc_cb *self);
+static int nsc_ircc_read_dongle_id (int iobase);
+static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id);
+
+static int nsc_ircc_net_init(struct net_device *dev);
+static int nsc_ircc_net_open(struct net_device *dev);
+static int nsc_ircc_net_close(struct net_device *dev);
+static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev);
#ifdef CONFIG_APM
-static int nsc_fir_apmproc(apm_event_t event);
+static int nsc_ircc_apmproc(apm_event_t event);
#endif /* CONFIG_APM */
+
/*
- * Function nsc_fir_init ()
+ * Function nsc_ircc_init ()
*
* Initialize chip. Just try to find out how many chips we are dealing with
* and where they are
*/
-int __init nsc_fir_init(void)
+int __init nsc_ircc_init(void)
{
+ chipio_t info;
+ nsc_chip_t *chip;
int ret = -ENODEV;
- int ioaddr;
- int i;
+ int cfg_base;
+ int cfg, id;
+ int reg;
+ int i = 0;
+
+ /* Probe for all the NSC chipsets we know about */
+ for (chip=chips; chip->name ; chip++,i++) {
+ IRDA_DEBUG(2, __FUNCTION__"(), Probing for %s ...\n",
+ chip->name);
+
+ /* Try all config registers for this chip */
+ for (cfg=0; cfg<3; cfg++) {
+ cfg_base = chip->cfg[cfg];
+ if (!cfg_base)
+ continue;
+
+ memset(&info, 0, sizeof(chipio_t));
+ info.cfg_base = cfg_base;
+ info.fir_base = io[i];
+ info.dma = dma[i];
+ info.irq = irq[i];
+
+ /* Read index register */
+ reg = inb(cfg_base);
+ if (reg == 0xff) {
+ IRDA_DEBUG(2, __FUNCTION__
+ "() no chip at 0x%03x\n", cfg_base);
+ continue;
+ }
+
+ /* Read chip identification register */
+ outb(chip->cid_index, cfg_base);
+ id = inb(cfg_base+1);
+ if ((id & chip->cid_mask) == chip->cid_value) {
+ IRDA_DEBUG(2, __FUNCTION__
+ "() Found %s chip, revision=%d\n",
+ chip->name, id & ~chip->cid_mask);
+ /*
+ * If the user supplies the base address, then
+ * we init the chip, if not we probe the values
+ * set by the BIOS
+ */
+ if (io[i] < 2000) {
+ chip->init(chip, &info);
+ } else
+ chip->probe(chip, &info);
+ if (nsc_ircc_open(i, &info) == 0)
+ ret = 0;
+ i++;
+ } else {
+ IRDA_DEBUG(2, __FUNCTION__
+ "(), Wrong chip id=0x%02x\n", id);
+ }
+ }
+
+ }
#ifdef CONFIG_APM
- apm_register_callback(nsc_fir_apmproc);
+ /* Make sure at least one chip was found before enabling APM */
+ if (ret == 0)
+ apm_register_callback(nsc_ircc_apmproc);
#endif /* CONFIG_APM */
- for (i=0; (io[i] < 2000) && (i < 5); i++) {
- ioaddr = io[i];
- if (check_region(ioaddr, CHIP_IO_EXTENT) < 0)
- continue;
- if (nsc_fir_open(i, io[i], io2[i], irq[i], dma[i]) == 0)
- {
-#ifdef CONFIG_NSC_FIR_MULTIPLE
- ret = 0;
-#else
- return 0;
-#endif
- }
- }
-
return ret;
}
/*
- * Function nsc_fir_cleanup ()
+ * Function nsc_ircc_cleanup ()
*
* Close all configured chips
*
*/
#ifdef MODULE
-static void nsc_fir_cleanup(void)
+static void nsc_ircc_cleanup(void)
{
int i;
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
#ifdef CONFIG_APM
- apm_unregister_callback(nsc_fir_apmproc);
+ apm_unregister_callback(nsc_ircc_apmproc);
#endif /* CONFIG_APM */
-
- for (i=0; i < 5; i++) {
+ for (i=0; i < 4; i++) {
if (dev_self[i])
- nsc_fir_close(dev_self[i]);
+ nsc_ircc_close(dev_self[i]);
}
}
#endif /* MODULE */
/*
- * Function nsc_fir_open (iobase, irq)
+ * Function nsc_ircc_open (iobase, irq)
*
* Open driver instance
*
*/
-static int
-nsc_fir_open(int i, unsigned int iobase, unsigned int board_addr,
- unsigned int irq, unsigned int dma)
+static int nsc_ircc_open(int i, chipio_t *info)
{
struct net_device *dev;
- struct nsc_fir_cb *self;
- int dongle_id;
+ struct nsc_ircc_cb *self;
int ret;
int err;
IRDA_DEBUG(2, __FUNCTION__ "()\n");
- if ((dongle_id = nsc_fir_probe(iobase, board_addr, irq, dma)) == -1)
+ if ((nsc_ircc_setup(info)) == -1)
return -1;
- /*
- * Allocate new instance of the driver
- */
- self = kmalloc(sizeof(struct nsc_fir_cb), GFP_KERNEL);
+ /* Allocate new instance of the driver */
+ self = kmalloc(sizeof(struct nsc_ircc_cb), GFP_KERNEL);
if (self == NULL) {
ERROR(__FUNCTION__ "(), can't allocate memory for "
"control block!\n");
return -ENOMEM;
}
- memset(self, 0, sizeof(struct nsc_fir_cb));
+ memset(self, 0, sizeof(struct nsc_ircc_cb));
spin_lock_init(&self->lock);
/* Need to store self somewhere */
dev_self[i] = self;
+ self->index = i;
/* Initialize IO */
- self->io.iobase = iobase;
- self->io.irq = irq;
- self->io.io_ext = CHIP_IO_EXTENT;
- self->io.dma = dma;
+ self->io.cfg_base = info->cfg_base;
+ self->io.fir_base = info->fir_base;
+ self->io.irq = info->irq;
+ self->io.fir_ext = CHIP_IO_EXTENT;
+ self->io.dma = info->dma;
self->io.fifo_size = 32;
-
- /* Lock the port that we need */
- ret = check_region(self->io.iobase, self->io.io_ext);
+
+ /* Reserve the ioports that we need */
+ ret = check_region(self->io.fir_base, self->io.fir_ext);
if (ret < 0) {
- IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- self->io.iobase);
- /* nsc_fir_cleanup(self->self); */
+ WARNING(__FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ self->io.fir_base);
+ dev_self[i] = NULL;
+ kfree(self);
return -ENODEV;
}
- request_region(self->io.iobase, self->io.io_ext, driver_name);
+ request_region(self->io.fir_base, self->io.fir_ext, driver_name);
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&self->qos);
@@ -268,13 +317,16 @@ nsc_fir_open(int i, unsigned int iobase, unsigned int board_addr,
/* Allocate memory if needed */
self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
GFP_KERNEL|GFP_DMA);
- if (self->rx_buff.head == NULL)
+ if (self->rx_buff.head == NULL) {
+ kfree(self);
return -ENOMEM;
+ }
memset(self->rx_buff.head, 0, self->rx_buff.truesize);
self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
GFP_KERNEL|GFP_DMA);
if (self->tx_buff.head == NULL) {
+ kfree(self);
kfree(self->rx_buff.head);
return -ENOMEM;
}
@@ -298,12 +350,12 @@ nsc_fir_open(int i, unsigned int iobase, unsigned int board_addr,
self->netdev = dev;
/* Override the network functions we need to use */
- dev->init = nsc_fir_net_init;
- dev->hard_start_xmit = nsc_fir_hard_xmit_sir;
- dev->open = nsc_fir_net_open;
- dev->stop = nsc_fir_net_close;
- dev->do_ioctl = nsc_fir_net_ioctl;
- dev->get_stats = nsc_fir_net_get_stats;
+ dev->init = nsc_ircc_net_init;
+ dev->hard_start_xmit = nsc_ircc_hard_xmit_sir;
+ dev->open = nsc_ircc_net_open;
+ dev->stop = nsc_ircc_net_close;
+ dev->do_ioctl = nsc_ircc_net_ioctl;
+ dev->get_stats = nsc_ircc_net_get_stats;
rtnl_lock();
err = register_netdevice(dev);
@@ -312,23 +364,33 @@ nsc_fir_open(int i, unsigned int iobase, unsigned int board_addr,
ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
return -1;
}
-
MESSAGE("IrDA: Registered device %s\n", dev->name);
+
+ /* Check if user has supplied the dongle id or not */
+ if (!dongle_id) {
+ dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base);
+
+ MESSAGE("%s, Found dongle: %s\n", driver_name,
+ dongle_types[dongle_id]);
+ } else {
+ MESSAGE("%s, Using dongle: %s\n", driver_name,
+ dongle_types[dongle_id]);
+ }
self->io.dongle_id = dongle_id;
- nsc_fir_init_dongle_interface(iobase, dongle_id);
+ nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id);
return 0;
}
#ifdef MODULE
/*
- * Function nsc_fir_close (self)
+ * Function nsc_ircc_close (self)
*
* Close driver instance
*
*/
-static int nsc_fir_close(struct nsc_fir_cb *self)
+static int nsc_ircc_close(struct nsc_ircc_cb *self)
{
int iobase;
@@ -336,7 +398,7 @@ static int nsc_fir_close(struct nsc_fir_cb *self)
ASSERT(self != NULL, return -1;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Remove netdevice */
if (self->netdev) {
@@ -347,8 +409,8 @@ static int nsc_fir_close(struct nsc_fir_cb *self)
/* Release the PORT that this driver is using */
IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n",
- self->io.iobase);
- release_region(self->io.iobase, self->io.io_ext);
+ self->io.fir_base);
+ release_region(self->io.fir_base, self->io.fir_ext);
if (self->tx_buff.head)
kfree(self->tx_buff.head);
@@ -356,37 +418,39 @@ static int nsc_fir_close(struct nsc_fir_cb *self)
if (self->rx_buff.head)
kfree(self->rx_buff.head);
+ dev_self[self->index] = NULL;
kfree(self);
-
+
return 0;
}
#endif /* MODULE */
/*
- * Function nsc_fir_init_807 (iobase, board_addr, irq, dma)
+ * Function nsc_ircc_init_108 (iobase, cfg_base, irq, dma)
*
* Initialize the NSC '108 chip
*
*/
-static void nsc_fir_init_807(int iobase, int board_addr, int irq, int dma)
+static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info)
{
+ int cfg_base = info->cfg_base;
__u8 temp=0;
- outb(2, board_addr); /* Mode Control Register (MCTL) */
- outb(0x00, board_addr+1); /* Disable device */
+ outb(2, cfg_base); /* Mode Control Register (MCTL) */
+ outb(0x00, cfg_base+1); /* Disable device */
/* Base Address and Interrupt Control Register (BAIC) */
- outb(0, board_addr);
- switch (iobase) {
- case 0x3e8: outb(0x14, board_addr+1); break;
- case 0x2e8: outb(0x15, board_addr+1); break;
- case 0x3f8: outb(0x16, board_addr+1); break;
- case 0x2f8: outb(0x17, board_addr+1); break;
+ outb(0, cfg_base);
+ switch (info->fir_base) {
+ case 0x3e8: outb(0x14, cfg_base+1); break;
+ case 0x2e8: outb(0x15, cfg_base+1); break;
+ case 0x3f8: outb(0x16, cfg_base+1); break;
+ case 0x2f8: outb(0x17, cfg_base+1); break;
default: ERROR(__FUNCTION__ "(), invalid base_address");
}
/* Control Signal Routing Register (CSRT) */
- switch (irq) {
+ switch (info->irq) {
case 3: temp = 0x01; break;
case 4: temp = 0x02; break;
case 5: temp = 0x03; break;
@@ -396,90 +460,242 @@ static void nsc_fir_init_807(int iobase, int board_addr, int irq, int dma)
case 15: temp = 0x07; break;
default: ERROR(__FUNCTION__ "(), invalid irq");
}
- outb(1, board_addr);
+ outb(1, cfg_base);
- switch (dma) {
- case 0: outb(0x08+temp, board_addr+1); break;
- case 1: outb(0x10+temp, board_addr+1); break;
- case 3: outb(0x18+temp, board_addr+1); break;
+ switch (info->dma) {
+ case 0: outb(0x08+temp, cfg_base+1); break;
+ case 1: outb(0x10+temp, cfg_base+1); break;
+ case 3: outb(0x18+temp, cfg_base+1); break;
default: ERROR(__FUNCTION__ "(), invalid dma");
}
- outb(2, board_addr); /* Mode Control Register (MCTL) */
- outb(0x03, board_addr+1); /* Enable device */
+ outb(2, cfg_base); /* Mode Control Register (MCTL) */
+ outb(0x03, cfg_base+1); /* Enable device */
+
+ return 0;
+}
+
+/*
+ * Function nsc_ircc_probe_108 (chip, info)
+ *
+ *
+ *
+ */
+static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info)
+{
+ int cfg_base = info->cfg_base;
+ int reg;
+
+ /* Read address and interrupt control register (BAIC) */
+ outb(CFG_BAIC, cfg_base);
+ reg = inb(cfg_base+1);
+
+ switch (reg & 0x03) {
+ case 0:
+ info->fir_base = 0x3e8;
+ break;
+ case 1:
+ info->fir_base = 0x2e8;
+ break;
+ case 2:
+ info->fir_base = 0x3f8;
+ break;
+ case 3:
+ info->fir_base = 0x2f8;
+ break;
+ }
+ info->sir_base = info->fir_base;
+ IRDA_DEBUG(2, __FUNCTION__ "(), probing fir_base=0x%03x\n",
+ info->fir_base);
+
+ /* Read control signals routing register (CSRT) */
+ outb(CFG_CSRT, cfg_base);
+ reg = inb(cfg_base+1);
+
+ switch (reg & 0x07) {
+ case 0:
+ info->irq = -1;
+ break;
+ case 1:
+ info->irq = 3;
+ break;
+ case 2:
+ info->irq = 4;
+ break;
+ case 3:
+ info->irq = 5;
+ break;
+ case 4:
+ info->irq = 7;
+ break;
+ case 5:
+ info->irq = 9;
+ break;
+ case 6:
+ info->irq = 11;
+ break;
+ case 7:
+ info->irq = 15;
+ break;
+ }
+ IRDA_DEBUG(2, __FUNCTION__ "(), probing irq=%d\n", info->irq);
+
+ /* Currently we only read Rx DMA but it will also be used for Tx */
+ switch ((reg >> 3) & 0x03) {
+ case 0:
+ info->dma = -1;
+ break;
+ case 1:
+ info->dma = 0;
+ break;
+ case 2:
+ info->dma = 1;
+ break;
+ case 3:
+ info->dma = 3;
+ break;
+ }
+ IRDA_DEBUG(2, __FUNCTION__ "(), probing dma=%d\n", info->dma);
+
+ /* Read mode control register (MCTL) */
+ outb(CFG_MCTL, cfg_base);
+ reg = inb(cfg_base+1);
+
+ info->enabled = reg & 0x01;
+ info->suspended = !((reg >> 1) & 0x01);
+
+ return 0;
}
/*
- * Function nsc_fir_init_338 (iobase, board_addr, irq, dma)
+ * Function nsc_ircc_init_338 (chip, info)
*
* Initialize the NSC '338 chip. Remember that the 87338 needs two
* consecutive writes to the data registers while CPU interrupts are
* disabled. The 97338 does not require this, but shouldn't be any
* harm if we do it anyway.
*/
-static void nsc_fir_init_338(int iobase, int board_addr, int irq, int dma)
+static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info)
{
/* No init yet */
+
+ return 0;
}
-static int nsc_fir_find_chip(int board_addr)
+/*
+ * Function nsc_ircc_probe_338 (chip, info)
+ *
+ *
+ *
+ */
+static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info)
{
- __u8 index, id;
+ int cfg_base = info->cfg_base;
+ int reg, com = 0;
+ int pnp;
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
+ /* Read funtion enable register (FER) */
+ outb(CFG_FER, cfg_base);
+ reg = inb(cfg_base+1);
- /* Read index register */
- index = inb(board_addr);
- if (index == 0xff) {
- IRDA_DEBUG(0, __FUNCTION__ "(), no chip at 0x%03x\n",
- board_addr);
- return -1;
- }
+ info->enabled = (reg >> 2) & 0x01;
+
+ /* Check if we are in Legacy or PnP mode */
+ outb(CFG_PNP0, cfg_base);
+ reg = inb(cfg_base+1);
+
+ pnp = (reg >> 4) & 0x01;
+ if (pnp) {
+ IRDA_DEBUG(2, "(), Chip is in PnP mode\n");
+ outb(0x46, cfg_base);
+ reg = (inb(cfg_base+1) & 0xfe) << 2;
+
+ outb(0x47, cfg_base);
+ reg |= ((inb(cfg_base+1) & 0xfc) << 8);
- /* Read chip identification register (SID) for the PC97338 */
- outb(8, board_addr);
- id = inb(board_addr+1);
- if ((id & 0xf0) == PC97338) {
- MESSAGE("%s, Found NSC PC97338 chip, revision=%d\n",
- driver_name, id & 0x0f);
- return PC97338;
- }
-
- /* Read device identification (DID) for the PC87108 */
- outb(5, board_addr);
- id = inb(board_addr+1);
- if ((id & 0xf0) == PC87108) {
- MESSAGE("%s, Found NSC PC87108 chip, revision=%d\n",
- driver_name, id & 0x0f);
- return PC87108;
+ info->fir_base = reg;
+ } else {
+ /* Read function address register (FAR) */
+ outb(CFG_FAR, cfg_base);
+ reg = inb(cfg_base+1);
+
+ switch ((reg >> 4) & 0x03) {
+ case 0:
+ info->fir_base = 0x3f8;
+ break;
+ case 1:
+ info->fir_base = 0x2f8;
+ break;
+ case 2:
+ com = 3;
+ break;
+ case 3:
+ com = 4;
+ break;
+ }
+
+ if (com) {
+ switch ((reg >> 6) & 0x03) {
+ case 0:
+ if (com == 3)
+ info->fir_base = 0x3e8;
+ else
+ info->fir_base = 0x2e8;
+ break;
+ case 1:
+ if (com == 3)
+ info->fir_base = 0x338;
+ else
+ info->fir_base = 0x238;
+ break;
+ case 2:
+ if (com == 3)
+ info->fir_base = 0x2e8;
+ else
+ info->fir_base = 0x2e0;
+ break;
+ case 3:
+ if (com == 3)
+ info->fir_base = 0x220;
+ else
+ info->fir_base = 0x228;
+ break;
+ }
+ }
}
+ info->sir_base = info->fir_base;
+
+ /* Read PnP register 1 (PNP1) */
+ outb(CFG_PNP1, cfg_base);
+ reg = inb(cfg_base+1);
+
+ info->irq = reg >> 4;
+
+ /* Read PnP register 3 (PNP3) */
+ outb(CFG_PNP3, cfg_base);
+ reg = inb(cfg_base+1);
+
+ info->dma = (reg & 0x07) - 1;
- return -1;
+ /* Read power and test register (PTR) */
+ outb(CFG_PTR, cfg_base);
+ reg = inb(cfg_base+1);
+
+ info->suspended = reg & 0x01;
+
+ return 0;
}
/*
- * Function nsc_fir_probe (iobase, board_addr, irq, dma)
+ * Function nsc_ircc_setup (info)
*
* Returns non-negative on success.
*
*/
-static int nsc_fir_probe(int iobase, int board_addr, int irq, int dma)
+static int nsc_ircc_setup(chipio_t *info)
{
int version;
- __u8 chip;
-
- chip = nsc_fir_find_chip(board_addr);
- switch (chip) {
- case PC87108:
- nsc_fir_init_807(iobase, board_addr, irq, dma);
- break;
- case PC97338:
- nsc_fir_init_338(iobase, board_addr, irq, dma);
- break;
- default:
- /* Found no chip */
- return -1;
- }
+ int iobase = info->fir_base;
/* Read the Module ID */
switch_bank(iobase, BANK3);
@@ -490,23 +706,13 @@ static int nsc_fir_probe(int iobase, int board_addr, int irq, int dma)
ERROR("%s, Wrong chip version %02x\n", driver_name, version);
return -1;
}
- MESSAGE("%s, Found chip at base=0x%04x\n", driver_name, board_addr);
+ MESSAGE("%s, Found chip at base=0x%03x\n", driver_name,
+ info->cfg_base);
/* Switch to advanced mode */
switch_bank(iobase, BANK2);
outb(ECR1_EXT_SL, iobase+ECR1);
switch_bank(iobase, BANK0);
-
- /* Check if user has supplied the dongle id or not */
- if (!dongle_id) {
- dongle_id = nsc_fir_read_dongle_id(iobase);
-
- MESSAGE("%s, Found dongle: %s\n", driver_name,
- dongle_types[dongle_id]);
- } else {
- MESSAGE("%s, Using dongle: %s\n", driver_name,
- dongle_types[dongle_id]);
- }
/* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
switch_bank(iobase, BANK0);
@@ -533,24 +739,21 @@ static int nsc_fir_probe(int iobase, int board_addr, int irq, int dma)
switch_bank(iobase, BANK0);
outb(IER_RXHDL_IE, iobase+IER);
- return dongle_id;
+ return 0;
}
/*
- * Function nsc_fir_read_dongle_id (void)
+ * Function nsc_ircc_read_dongle_id (void)
*
* Try to read dongle indentification. This procedure needs to be executed
* once after power-on/reset. It also needs to be used whenever you suspect
* that the user may have plugged/unplugged the IrDA Dongle.
- *
*/
-static int nsc_fir_read_dongle_id (int iobase)
+static int nsc_ircc_read_dongle_id (int iobase)
{
int dongle_id;
__u8 bank;
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
bank = inb(iobase+BSR);
/* Select Bank 7 */
@@ -568,8 +771,7 @@ static int nsc_fir_read_dongle_id (int iobase)
#ifdef BROKEN_DONGLE_ID
if (dongle_id == 0x0a)
dongle_id = 0x09;
-#endif
-
+#endif
/* Go back to bank 0 before returning */
switch_bank(iobase, BANK0);
@@ -579,14 +781,14 @@ static int nsc_fir_read_dongle_id (int iobase)
}
/*
- * Function nsc_fir_init_dongle_interface (iobase, dongle_id)
+ * Function nsc_ircc_init_dongle_interface (iobase, dongle_id)
*
* This function initializes the dongle for the transceiver that is
* used. This procedure needs to be executed once after
* power-on/reset. It also needs to be used whenever you suspect that
* the dongle is changed.
*/
-static void nsc_fir_init_dongle_interface (int iobase, int dongle_id)
+static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id)
{
int bank;
@@ -625,11 +827,11 @@ static void nsc_fir_init_dongle_interface (int iobase, int dongle_id)
dongle_types[dongle_id]);
break;
case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
- dongle_types[dongle_id]);
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
+ dongle_types[dongle_id]);
break;
case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
- outb_p(0x28, iobase+7); /* Set irsl[0-2] as output */
+ outb(0x28, iobase+7); /* Set irsl[0-2] as output */
break;
case 0x0A: /* same as */
case 0x0B: /* Reserved */
@@ -668,18 +870,16 @@ static void nsc_fir_init_dongle_interface (int iobase, int dongle_id)
} /* set_up_dongle_interface */
/*
- * Function nsc_fir_change_dongle_speed (iobase, speed, dongle_id)
+ * Function nsc_ircc_change_dongle_speed (iobase, speed, dongle_id)
*
* Change speed of the attach dongle
*
*/
-static void nsc_fir_change_dongle_speed(int iobase, int speed, int dongle_id)
+static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id)
{
unsigned long flags;
__u8 bank;
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
/* Save current bank */
bank = inb(iobase+BSR);
@@ -714,11 +914,14 @@ static void nsc_fir_change_dongle_speed(int iobase, int speed, int dongle_id)
dongle_types[dongle_id]);
break;
case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
dongle_types[dongle_id]);
+ outb(0x00, iobase+4);
+ if (speed > 115200)
+ outb(0x01, iobase+4);
+ break;
case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
- switch_bank(iobase, BANK7);
- outb_p(0x01, iobase+4);
+ outb(0x01, iobase+4);
if (speed == 4000000) {
save_flags(flags);
@@ -727,7 +930,7 @@ static void nsc_fir_change_dongle_speed(int iobase, int speed, int dongle_id)
outb(0x80, iobase+4);
restore_flags(flags);
} else
- outb_p(0x00, iobase+4);
+ outb(0x00, iobase+4);
break;
case 0x0A: /* same as */
case 0x0B: /* Reserved */
@@ -754,12 +957,12 @@ static void nsc_fir_change_dongle_speed(int iobase, int speed, int dongle_id)
}
/*
- * Function nsc_fir_change_speed (self, baud)
+ * Function nsc_ircc_change_speed (self, baud)
*
* Change the speed of the device
*
*/
-static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 speed)
+static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed)
{
struct net_device *dev = self->netdev;
__u8 mcr = MCR_SIR;
@@ -770,7 +973,7 @@ static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 speed)
ASSERT(self != NULL, return;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Update accounting for new speed */
self->io.speed = speed;
@@ -821,7 +1024,7 @@ static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 speed)
outb(mcr | MCR_TX_DFR, iobase+MCR);
/* Give some hits to the transceiver */
- nsc_fir_change_dongle_speed(iobase, speed, self->io.dongle_id);
+ nsc_ircc_change_dongle_speed(iobase, speed, self->io.dongle_id);
/* Set FIFO threshold to TX17, RX16 */
switch_bank(iobase, BANK0);
@@ -844,12 +1047,12 @@ static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 speed)
switch_bank(iobase, BANK0);
if (speed > 115200) {
/* Install FIR xmit handler */
- dev->hard_start_xmit = nsc_fir_hard_xmit_fir;
+ dev->hard_start_xmit = nsc_ircc_hard_xmit_fir;
outb(IER_SFIF_IE, iobase+IER);
- nsc_fir_dma_receive(self);
+ nsc_ircc_dma_receive(self);
} else {
/* Install SIR xmit handler */
- dev->hard_start_xmit = nsc_fir_hard_xmit_sir;
+ dev->hard_start_xmit = nsc_ircc_hard_xmit_sir;
outb(IER_RXHDL_IE, iobase+IER);
}
@@ -858,24 +1061,24 @@ static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 speed)
}
/*
- * Function nsc_fir_hard_xmit (skb, dev)
+ * Function nsc_ircc_hard_xmit (skb, dev)
*
* Transmit the frame!
*
*/
-static int nsc_fir_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
+static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
{
- struct nsc_fir_cb *self;
+ struct nsc_ircc_cb *self;
unsigned long flags;
int iobase;
__u32 speed;
__u8 bank;
- self = (struct nsc_fir_cb *) dev->priv;
+ self = (struct nsc_ircc_cb *) dev->priv;
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Lock transmit buffer */
if (irda_lock((void *) &dev->tbusy) == FALSE)
@@ -894,6 +1097,8 @@ static int nsc_fir_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
self->tx_buff.truesize);
+
+ self->stats.tx_bytes += self->tx_buff.len;
/* Add interrupt on tx low level (will fire immediately) */
switch_bank(iobase, BANK0);
@@ -909,20 +1114,17 @@ static int nsc_fir_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
return 0;
}
-static int nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
+static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
{
- struct nsc_fir_cb *self;
+ struct nsc_ircc_cb *self;
unsigned long flags;
int iobase;
__u32 speed;
__u8 bank;
int mtt, diff;
- self = (struct nsc_fir_cb *) dev->priv;
-
- ASSERT(self != NULL, return 0;);
-
- iobase = self->io.iobase;
+ self = (struct nsc_ircc_cb *) dev->priv;
+ iobase = self->io.fir_base;
/* Lock transmit buffer */
if (irda_lock((void *) &dev->tbusy) == FALSE)
@@ -942,6 +1144,8 @@ static int nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
self->tx_fifo.queue[self->tx_fifo.free].len = skb->len;
self->tx_fifo.tail += skb->len;
+ self->stats.tx_bytes += skb->len;
+
memcpy(self->tx_fifo.queue[self->tx_fifo.free].start, skb->data,
skb->len);
@@ -950,10 +1154,11 @@ static int nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
/* Start transmit only if there is currently no transmit going on */
if (self->tx_fifo.len == 1) {
+ /* Check if we must wait the min turn time or not */
mtt = irda_get_mtt(skb);
if (mtt) {
/* Check how much time we have used already */
- do_gettimeofday(&self->now);
+ get_fast_time(&self->now);
diff = self->now.tv_usec - self->stamp.tv_usec;
if (diff < 0)
diff += 1000000;
@@ -963,9 +1168,15 @@ static int nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
*/
if (mtt > diff) {
mtt -= diff;
+
+ /*
+ * Use timer if delay larger than 125 us, and
+ * use udelay for smaller values which should
+ * be acceptable
+ */
if (mtt > 125) {
/* Adjust for timer resolution */
- mtt = mtt / 125 + 1;
+ mtt = mtt / 125;
/* Setup timer */
switch_bank(iobase, BANK4);
@@ -985,34 +1196,35 @@ static int nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
} else
udelay(mtt);
}
- }
-
+ }
/* Enable DMA interrupt */
switch_bank(iobase, BANK0);
outb(IER_DMA_IE, iobase+IER);
- nsc_fir_dma_xmit(self, iobase);
+
+ /* Transmit frame */
+ nsc_ircc_dma_xmit(self, iobase);
}
+ out:
/* Not busy transmitting anymore if window is not full */
- if (self->tx_fifo.len < MAX_WINDOW)
+ if (self->tx_fifo.free < MAX_TX_WINDOW)
dev->tbusy = 0;
- out:
+
/* Restore bank register */
outb(bank, iobase+BSR);
spin_unlock_irqrestore(&self->lock, flags);
-
dev_kfree_skb(skb);
return 0;
}
/*
- * Function nsc_fir_dma_xmit (self, iobase)
+ * Function nsc_ircc_dma_xmit (self, iobase)
*
* Transmit data using DMA
*
*/
-static void nsc_fir_dma_xmit(struct nsc_fir_cb *self, int iobase)
+static void nsc_ircc_dma_xmit(struct nsc_ircc_cb *self, int iobase)
{
int bsr;
@@ -1043,13 +1255,13 @@ static void nsc_fir_dma_xmit(struct nsc_fir_cb *self, int iobase)
}
/*
- * Function nsc_fir_pio_xmit (self, iobase)
+ * Function nsc_ircc_pio_xmit (self, iobase)
*
* Transmit data using PIO. Returns the number of bytes that actually
* got transfered
*
*/
-static int nsc_fir_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
+static int nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
{
int actual = 0;
__u8 bank;
@@ -1064,6 +1276,7 @@ static int nsc_fir_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
IRDA_DEBUG(4, __FUNCTION__
"(), warning, FIFO not empty yet!\n");
+ /* FIFO may still be filled to the Tx interrupt threshold */
fifo_size -= 17;
}
@@ -1083,13 +1296,13 @@ static int nsc_fir_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
}
/*
- * Function nsc_fir_dma_xmit_complete (self)
+ * Function nsc_ircc_dma_xmit_complete (self)
*
* The transfer of a frame in finished. This function will only be called
* by the interrupt handler
*
*/
-static int nsc_fir_dma_xmit_complete(struct nsc_fir_cb *self)
+static int nsc_ircc_dma_xmit_complete(struct nsc_ircc_cb *self)
{
int iobase;
__u8 bank;
@@ -1097,7 +1310,7 @@ static int nsc_fir_dma_xmit_complete(struct nsc_fir_cb *self)
IRDA_DEBUG(2, __FUNCTION__ "()\n");
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Save current bank */
bank = inb(iobase+BSR);
@@ -1115,11 +1328,11 @@ static int nsc_fir_dma_xmit_complete(struct nsc_fir_cb *self)
outb(ASCR_TXUR, iobase+ASCR);
} else {
self->stats.tx_packets++;
- self->stats.tx_bytes += self->tx_buff.len;
}
-
+
+ /* Check if we need to change the speed */
if (self->new_speed) {
- nsc_fir_change_speed(self, self->new_speed);
+ nsc_ircc_change_speed(self, self->new_speed);
self->new_speed = 0;
}
@@ -1129,17 +1342,24 @@ static int nsc_fir_dma_xmit_complete(struct nsc_fir_cb *self)
/* Any frames to be sent back-to-back? */
if (self->tx_fifo.len) {
- nsc_fir_dma_xmit(self, iobase);
+ nsc_ircc_dma_xmit(self, iobase);
/* Not finished yet! */
ret = FALSE;
+ } else {
+ /* Reset Tx FIFO info */
+ self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
+ self->tx_fifo.tail = self->tx_buff.head;
}
- /* Not busy transmitting anymore */
- self->netdev->tbusy = 0;
+ /* Make sure we have room for more frames */
+ if (self->tx_fifo.free < MAX_TX_WINDOW) {
+ /* Not busy transmitting anymore */
+ self->netdev->tbusy = 0;
- /* Tell the network layer, that we can accept more frames */
- mark_bh(NET_BH);
+ /* Tell the network layer, that we can accept more frames */
+ mark_bh(NET_BH);
+ }
/* Restore bank */
outb(bank, iobase+BSR);
@@ -1148,20 +1368,18 @@ static int nsc_fir_dma_xmit_complete(struct nsc_fir_cb *self)
}
/*
- * Function nsc_fir_dma_receive (self)
+ * Function nsc_ircc_dma_receive (self)
*
* Get ready for receiving a frame. The device will initiate a DMA
* if it starts to receive a frame.
*
*/
-static int nsc_fir_dma_receive(struct nsc_fir_cb *self)
+static int nsc_ircc_dma_receive(struct nsc_ircc_cb *self)
{
int iobase;
__u8 bsr;
- ASSERT(self != NULL, return -1;);
-
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Reset Tx FIFO info */
self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
@@ -1184,7 +1402,9 @@ static int nsc_fir_dma_receive(struct nsc_fir_cb *self)
/* Reset Rx FIFO. This will also flush the ST_FIFO */
switch_bank(iobase, BANK0);
outb(FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
- self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0;
+
+ self->st_fifo.len = self->st_fifo.pending_bytes = 0;
+ self->st_fifo.tail = self->st_fifo.head = 0;
setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize,
DMA_RX_MODE);
@@ -1200,18 +1420,18 @@ static int nsc_fir_dma_receive(struct nsc_fir_cb *self)
}
/*
- * Function nsc_fir_dma_receive_complete (self)
+ * Function nsc_ircc_dma_receive_complete (self)
*
* Finished with receiving frames
*
*
*/
-static int nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase)
+static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase)
{
- struct sk_buff *skb;
struct st_fifo *st_fifo;
- __u8 bank;
+ struct sk_buff *skb;
__u8 status;
+ __u8 bank;
int len;
st_fifo = &self->st_fifo;
@@ -1219,22 +1439,27 @@ static int nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase)
/* Save current bank */
bank = inb(iobase+BSR);
- /* Read status FIFO */
+ /* Read all entries in status FIFO */
switch_bank(iobase, BANK5);
while ((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) {
- st_fifo->entries[st_fifo->tail].status = status;
+ /* We must empty the status FIFO no matter what */
+ len = inb(iobase+RFLFL) | ((inb(iobase+RFLFH) & 0x1f) << 8);
- st_fifo->entries[st_fifo->tail].len = inb(iobase+RFLFL);
- st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
-
+ if (st_fifo->tail >= MAX_RX_WINDOW)
+ continue;
+
+ st_fifo->entries[st_fifo->tail].status = status;
+ st_fifo->entries[st_fifo->tail].len = len;
+ st_fifo->pending_bytes += len;
st_fifo->tail++;
st_fifo->len++;
}
/* Try to process all entries in status FIFO */
- while (st_fifo->len) {
+ while (st_fifo->len > 0) {
/* Get first entry */
status = st_fifo->entries[st_fifo->head].status;
len = st_fifo->entries[st_fifo->head].len;
+ st_fifo->pending_bytes -= len;
st_fifo->head++;
st_fifo->len--;
@@ -1265,36 +1490,46 @@ static int nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase)
if (status & FRM_ST_OVR2)
self->stats.rx_fifo_errors++;
} else {
- /* Check if we have transfered all data to memory */
- switch_bank(iobase, BANK0);
- if (inb(iobase+LSR) & LSR_RXDA) {
- /* Put this entry back in fifo */
- st_fifo->head--;
- st_fifo->len++;
- st_fifo->entries[st_fifo->head].status = status;
- st_fifo->entries[st_fifo->head].len = len;
-
- /* Restore bank register */
- outb(bank, iobase+BSR);
+ /*
+ * First we must make sure that the frame we
+ * want to deliver is all in main memory. If we
+ * cannot tell, then we check if the Rx FIFO is
+ * empty. If not then we will have to take a nap
+ * and try again later.
+ */
+ if (st_fifo->pending_bytes < self->io.fifo_size) {
+ switch_bank(iobase, BANK0);
+ if (inb(iobase+LSR) & LSR_RXDA) {
+ /* Put this entry back in fifo */
+ st_fifo->head--;
+ st_fifo->len++;
+ st_fifo->pending_bytes += len;
+ st_fifo->entries[st_fifo->head].status = status;
+ st_fifo->entries[st_fifo->head].len = len;
- return FALSE; /* I'll be back! */
+ /* Restore bank register */
+ outb(bank, iobase+BSR);
+
+ return FALSE; /* I'll be back! */
+ }
}
/*
- * Remember when we received this frame, so we can
+ * Remember the time we received this frame, so we can
* reduce the min turn time a bit since we will know
* how much time we have used for protocol processing
*/
- do_gettimeofday(&self->stamp);
+ get_fast_time(&self->stamp);
skb = dev_alloc_skb(len+1);
if (skb == NULL) {
WARNING(__FUNCTION__ "(), memory squeeze, "
"dropping frame.\n");
-
+ self->stats.rx_dropped++;
+
/* Restore bank register */
outb(bank, iobase+BSR);
-
+
return FALSE;
}
@@ -1312,6 +1547,7 @@ static int nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase)
/* Move to next frame */
self->rx_buff.data += len;
+ self->stats.rx_bytes += len;
self->stats.rx_packets++;
skb->dev = self->netdev;
@@ -1327,21 +1563,17 @@ static int nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase)
}
/*
- * Function nsc_fir_pio_receive (self)
+ * Function nsc_ircc_pio_receive (self)
*
* Receive all data in receiver FIFO
*
*/
-static void nsc_fir_pio_receive(struct nsc_fir_cb *self)
+static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self)
{
- __u8 byte = 0x00;
+ __u8 byte;
int iobase;
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
- ASSERT(self != NULL, return;);
-
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Receive all characters in Rx FIFO */
do {
@@ -1352,20 +1584,19 @@ static void nsc_fir_pio_receive(struct nsc_fir_cb *self)
}
/*
- * Function nsc_fir_sir_interrupt (self, eir)
+ * Function nsc_ircc_sir_interrupt (self, eir)
*
* Handle SIR interrupt
*
*/
-static __u8 nsc_fir_sir_interrupt(struct nsc_fir_cb *self, int eir)
+static void nsc_ircc_sir_interrupt(struct nsc_ircc_cb *self, int eir)
{
int actual;
- __u8 new_ier = 0;
/* Check if transmit FIFO is low on data */
if (eir & EIR_TXLDL_EV) {
/* Write data left in transmit buffer */
- actual = nsc_fir_pio_write(self->io.iobase,
+ actual = nsc_ircc_pio_write(self->io.fir_base,
self->tx_buff.data,
self->tx_buff.len,
self->io.fifo_size);
@@ -1376,14 +1607,14 @@ static __u8 nsc_fir_sir_interrupt(struct nsc_fir_cb *self, int eir)
/* Check if finished */
if (self->tx_buff.len > 0)
- new_ier |= IER_TXLDL_IE;
+ self->ier = IER_TXLDL_IE;
else {
self->netdev->tbusy = 0; /* Unlock */
self->stats.tx_packets++;
mark_bh(NET_BH);
- new_ier |= IER_TXEMP_IE;
+ self->ier = IER_TXEMP_IE;
}
}
@@ -1392,56 +1623,62 @@ static __u8 nsc_fir_sir_interrupt(struct nsc_fir_cb *self, int eir)
/* Check if we need to change the speed? */
if (self->new_speed) {
IRDA_DEBUG(2, __FUNCTION__ "(), Changing speed!\n");
- nsc_fir_change_speed(self, self->new_speed);
+ nsc_ircc_change_speed(self, self->new_speed);
self->new_speed = 0;
- }
+ /* Check if we are going to FIR */
+ if (self->io.speed > 115200) {
+ /* Should wait for status FIFO interrupt */
+ self->ier = IER_SFIF_IE;
+
+ /* No need to do anymore SIR stuff */
+ return;
+ }
+ }
/* Turn around and get ready to receive some data */
self->io.direction = IO_RECV;
- new_ier |= IER_RXHDL_IE;
+ self->ier = IER_RXHDL_IE;
}
/* Rx FIFO threshold or timeout */
if (eir & EIR_RXHDL_EV) {
- nsc_fir_pio_receive(self);
+ nsc_ircc_pio_receive(self);
/* Keep receiving */
- new_ier |= IER_RXHDL_IE;
+ self->ier = IER_RXHDL_IE;
}
- return new_ier;
}
/*
- * Function nsc_fir_fir_interrupt (self, eir)
+ * Function nsc_ircc_fir_interrupt (self, eir)
*
* Handle MIR/FIR interrupt
*
*/
-static __u8 nsc_fir_fir_interrupt(struct nsc_fir_cb *self, int iobase, int eir)
+static void nsc_ircc_fir_interrupt(struct nsc_ircc_cb *self, int iobase,
+ int eir)
{
- __u8 new_ier = 0;
__u8 bank;
bank = inb(iobase+BSR);
- /* Status event, or end of frame detected in FIFO */
- if (eir & (EIR_SFIF_EV|EIR_LS_EV)) {
- if (nsc_fir_dma_receive_complete(self, iobase)) {
-
+ /* Status FIFO event*/
+ if (eir & EIR_SFIF_EV) {
+ if (nsc_ircc_dma_receive_complete(self, iobase)) {
/* Wait for next status FIFO interrupt */
- new_ier |= IER_SFIF_IE;
+ self->ier = IER_SFIF_IE;
} else {
- /* DMA not finished yet */
-
- /* Set timer value, resolution 125 us */
+ /*
+ * DMA not finished yet, so try again later, set
+ * timer value, resolution 125 us
+ */
switch_bank(iobase, BANK4);
- outb(0x0f, iobase+TMRL); /* 125 us * 15 */
+ outb(0x02, iobase+TMRL); /* 2 * 125 us */
outb(0x00, iobase+TMRH);
/* Start timer */
outb(IRCR1_TMR_EN, iobase+IRCR1);
-
- new_ier |= IER_TMR_IE;
+ self->ier = IER_TMR_IE | IER_SFIF_IE;
}
} else if (eir & EIR_TMR_EV) { /* Timer finished */
/* Disable timer */
@@ -1452,101 +1689,102 @@ static __u8 nsc_fir_fir_interrupt(struct nsc_fir_cb *self, int iobase, int eir)
switch_bank(iobase, BANK0);
outb(ASCR_CTE, iobase+ASCR);
- /* Check if this is a TX timer interrupt */
+ /* Check if this is a Tx timer interrupt */
if (self->io.direction == IO_XMIT) {
- nsc_fir_dma_xmit(self, iobase);
+ nsc_ircc_dma_xmit(self, iobase);
/* Interrupt on DMA */
- new_ier |= IER_DMA_IE;
+ self->ier = IER_DMA_IE;
} else {
/* Check if DMA has now finished */
- nsc_fir_dma_receive_complete(self, iobase);
+ nsc_ircc_dma_receive_complete(self, iobase);
- new_ier |= IER_SFIF_IE;
+ self->ier = IER_SFIF_IE;
}
- } else if (eir & EIR_DMA_EV) { /* Finished with transmission */
- if (nsc_fir_dma_xmit_complete(self)) {
+ } else if (eir & EIR_DMA_EV) {
+ /* Finished with all transmissions? */
+ if (nsc_ircc_dma_xmit_complete(self)) {
/* Check if there are more frames to be transmitted */
if (irda_device_txqueue_empty(self->netdev)) {
/* Prepare for receive */
- nsc_fir_dma_receive(self);
+ nsc_ircc_dma_receive(self);
- new_ier = IER_LS_IE|IER_SFIF_IE;
+ self->ier = IER_SFIF_IE;
}
} else {
/* Not finished yet, so interrupt on DMA again */
- new_ier |= IER_DMA_IE;
+ self->ier = IER_DMA_IE;
}
}
outb(bank, iobase+BSR);
-
- return new_ier;
}
/*
- * Function nsc_fir_interrupt (irq, dev_id, regs)
+ * Function nsc_ircc_interrupt (irq, dev_id, regs)
*
* An interrupt from the chip has arrived. Time to do some work
*
*/
-static void nsc_fir_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void nsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
- struct nsc_fir_cb *self;
- __u8 bsr, eir, ier;
+ struct nsc_ircc_cb *self;
+ __u8 bsr, eir;
int iobase;
if (!dev) {
- printk(KERN_WARNING "%s: irq %d for unknown device.\n",
- driver_name, irq);
+ WARNING("%s: irq %d for unknown device.\n", driver_name, irq);
return;
}
- self = (struct nsc_fir_cb *) dev->priv;
+ self = (struct nsc_ircc_cb *) dev->priv;
spin_lock(&self->lock);
dev->interrupt = 1;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
bsr = inb(iobase+BSR); /* Save current bank */
switch_bank(iobase, BANK0);
- ier = inb(iobase+IER);
- eir = inb(iobase+EIR) & ier; /* Mask out the interesting ones */
+ self->ier = inb(iobase+IER);
+ eir = inb(iobase+EIR) & self->ier; /* Mask out the interesting ones */
outb(0, iobase+IER); /* Disable interrupts */
if (eir) {
/* Dispatch interrupt handler for the current speed */
if (self->io.speed > 115200)
- ier = nsc_fir_fir_interrupt(self, iobase, eir);
+ nsc_ircc_fir_interrupt(self, iobase, eir);
else
- ier = nsc_fir_sir_interrupt(self, eir);
+ nsc_ircc_sir_interrupt(self, eir);
}
-
- outb(ier, iobase+IER); /* Restore interrupts */
- outb(bsr, iobase+BSR); /* Restore bank register */
+
+ outb(self->ier, iobase+IER); /* Restore interrupts */
+ outb(bsr, iobase+BSR); /* Restore bank register */
dev->interrupt = 0;
spin_unlock(&self->lock);
}
/*
- * Function nsc_fir_is_receiving (self)
+ * Function nsc_ircc_is_receiving (self)
*
* Return TRUE is we are currently receiving a frame
*
*/
-static int nsc_fir_is_receiving(struct nsc_fir_cb *self)
+static int nsc_ircc_is_receiving(struct nsc_ircc_cb *self)
{
+ unsigned long flags;
int status = FALSE;
int iobase;
__u8 bank;
ASSERT(self != NULL, return FALSE;);
+ spin_lock_irqsave(&self->lock, flags);
+
if (self->io.speed > 115200) {
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Check if rx FIFO is not empty */
bank = inb(iobase+BSR);
@@ -1559,16 +1797,18 @@ static int nsc_fir_is_receiving(struct nsc_fir_cb *self)
} else
status = (self->rx_buff.state != OUTSIDE_FRAME);
+ spin_unlock_irqrestore(&self->lock, flags);
+
return status;
}
/*
- * Function nsc_fir_net_init (dev)
+ * Function nsc_ircc_net_init (dev)
*
* Initialize network device
*
*/
-static int nsc_fir_net_init(struct net_device *dev)
+static int nsc_ircc_net_init(struct net_device *dev)
{
IRDA_DEBUG(4, __FUNCTION__ "()\n");
@@ -1581,29 +1821,29 @@ static int nsc_fir_net_init(struct net_device *dev)
}
/*
- * Function nsc_fir_net_open (dev)
+ * Function nsc_ircc_net_open (dev)
*
* Start the device
*
*/
-static int nsc_fir_net_open(struct net_device *dev)
+static int nsc_ircc_net_open(struct net_device *dev)
{
- struct nsc_fir_cb *self;
+ struct nsc_ircc_cb *self;
int iobase;
__u8 bank;
IRDA_DEBUG(4, __FUNCTION__ "()\n");
ASSERT(dev != NULL, return -1;);
- self = (struct nsc_fir_cb *) dev->priv;
+ self = (struct nsc_ircc_cb *) dev->priv;
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
-
- if (request_irq(self->io.irq, nsc_fir_interrupt, 0, dev->name,
- (void *) dev))
- {
+ iobase = self->io.fir_base;
+
+ if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, dev->name, dev)) {
+ WARNING("%s, unable to allocate irq=%d\n", driver_name,
+ self->io.irq);
return -EAGAIN;
}
/*
@@ -1611,6 +1851,8 @@ static int nsc_fir_net_open(struct net_device *dev)
* failure.
*/
if (request_dma(self->io.dma, dev->name)) {
+ WARNING("%s, unable to allocate dma=%d\n", driver_name,
+ self->io.dma);
free_irq(self->io.irq, self);
return -EAGAIN;
}
@@ -1642,22 +1884,22 @@ static int nsc_fir_net_open(struct net_device *dev)
}
/*
- * Function nsc_fir_net_close (dev)
+ * Function nsc_ircc_net_close (dev)
*
* Stop the device
*
*/
-static int nsc_fir_net_close(struct net_device *dev)
+static int nsc_ircc_net_close(struct net_device *dev)
{
- struct nsc_fir_cb *self;
+ struct nsc_ircc_cb *self;
int iobase;
__u8 bank;
IRDA_DEBUG(4, __FUNCTION__ "()\n");
ASSERT(dev != NULL, return -1;);
- self = (struct nsc_fir_cb *) dev->priv;
-
+
+ self = (struct nsc_ircc_cb *) dev->priv;
ASSERT(self != NULL, return 0;);
/* Stop device */
@@ -1669,7 +1911,7 @@ static int nsc_fir_net_close(struct net_device *dev)
irlap_close(self->irlap);
self->irlap = NULL;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
disable_dma(self->io.dma);
@@ -1692,15 +1934,15 @@ static int nsc_fir_net_close(struct net_device *dev)
}
/*
- * Function nsc_fir_net_ioctl (dev, rq, cmd)
+ * Function nsc_ircc_net_ioctl (dev, rq, cmd)
*
* Process IOCTL commands for this device
*
*/
-static int nsc_fir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct if_irda_req *irq = (struct if_irda_req *) rq;
- struct nsc_fir_cb *self;
+ struct nsc_ircc_cb *self;
unsigned long flags;
int ret = 0;
@@ -1718,13 +1960,13 @@ static int nsc_fir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
- nsc_fir_change_speed(self, irq->ifr_baudrate);
+ nsc_ircc_change_speed(self, irq->ifr_baudrate);
break;
case SIOCSMEDIABUSY: /* Set media busy */
irda_device_set_media_busy(self->netdev, TRUE);
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
- irq->ifr_receiving = nsc_fir_is_receiving(self);
+ irq->ifr_receiving = nsc_ircc_is_receiving(self);
break;
default:
ret = -EOPNOTSUPP;
@@ -1735,54 +1977,60 @@ static int nsc_fir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return ret;
}
-static struct net_device_stats *nsc_fir_net_get_stats(struct net_device *dev)
+static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev)
{
- struct nsc_fir_cb *self = (struct nsc_fir_cb *) dev->priv;
+ struct nsc_ircc_cb *self = (struct nsc_ircc_cb *) dev->priv;
return &self->stats;
}
#ifdef CONFIG_APM
-static void nsc_fir_suspend(struct nsc_fir_cb *self)
+static void nsc_ircc_suspend(struct nsc_ircc_cb *self)
{
- int i = 10;
-
MESSAGE("%s, Suspending\n", driver_name);
- if (self->suspend)
+ if (self->io.suspended)
return;
- self->suspend = 1;
-}
+ nsc_ircc_net_close(self->netdev);
+ self->io.suspended = 1;
+}
-static void nsc_fir_wakeup(struct nsc_fir_cb *self)
+static void nsc_ircc_wakeup(struct nsc_ircc_cb *self)
{
struct net_device *dev = self->netdev;
- unsigned long flags;
+ int iobase;
- if (!self->suspend)
+ if (!self->io.suspended)
return;
- save_flags(flags);
- cli();
+ iobase = self->io.fir_base;
- restore_flags(flags);
+ /* Switch to advanced mode */
+ switch_bank(iobase, BANK2);
+ outb(ECR1_EXT_SL, iobase+ECR1);
+ switch_bank(iobase, BANK0);
+
+ nsc_ircc_net_open(self->netdev);
+
MESSAGE("%s, Waking up\n", driver_name);
+
+ self->io.suspended = 0;
}
-static int nsc_fir_apmproc(apm_event_t event)
+static int nsc_ircc_apmproc(apm_event_t event)
{
- static int down = 0; /* Filter out double events */
+ static int down = 0; /* Filter out double events */
int i;
switch (event) {
case APM_SYS_SUSPEND:
case APM_USER_SUSPEND:
if (!down) {
- for (i = 0; i < 4; i++) {
+ for (i=0; i<4; i++) {
if (dev_self[i])
- nsc_fir_suspend(dev_self[i]);
+ nsc_ircc_suspend(dev_self[i]);
}
}
down = 1;
@@ -1790,9 +2038,9 @@ static int nsc_fir_apmproc(apm_event_t event)
case APM_NORMAL_RESUME:
case APM_CRITICAL_RESUME:
if (down) {
- for (i = 0; i < 4; i++) {
+ for (i=0; i<4; i++) {
if (dev_self[i])
- nsc_fir_wakeup(dev_self[i]);
+ nsc_ircc_wakeup(dev_self[i]);
}
}
down = 0;
@@ -1804,22 +2052,22 @@ static int nsc_fir_apmproc(apm_event_t event)
#ifdef MODULE
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
-MODULE_DESCRIPTION("NSC FIR IrDA Device Driver");
+MODULE_DESCRIPTION("NSC IrDA Device Driver");
MODULE_PARM(qos_mtt_bits, "i");
-MODULE_PARM(io, "1-4i");
-MODULE_PARM(io2, "1-4i");
+MODULE_PARM(io, "1-4i");
MODULE_PARM(irq, "1-4i");
+MODULE_PARM(dma, "1-4i");
MODULE_PARM(dongle_id, "i");
int init_module(void)
{
- return nsc_fir_init();
+ return nsc_ircc_init();
}
void cleanup_module(void)
{
- nsc_fir_cleanup();
+ nsc_ircc_cleanup();
}
#endif /* MODULE */
diff --git a/drivers/net/irda/smc-ircc.c b/drivers/net/irda/smc-ircc.c
index 1d857c2b0..48b38227e 100644
--- a/drivers/net/irda/smc-ircc.c
+++ b/drivers/net/irda/smc-ircc.c
@@ -1,12 +1,12 @@
/*********************************************************************
*
* Filename: smc-ircc.c
- * Version: 0.3
+ * Version: 0.4
* Description: Driver for the SMC Infrared Communications Controller
* Status: Experimental.
* Author: Thomas Davis (tadavis@jps.net)
* Created at:
- * Modified at: Wed Jan 5 12:38:06 2000
+ * Modified at: Fri Jan 21 09:41:08 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999-2000 Dag Brattli
@@ -28,11 +28,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
- * SIO's: SMC FDC37N869, FDC37C669
+ * SIO's: SMC FDC37N869, FDC37C669, FDC37N958
* Applicable Models : Fujitsu Lifebook 635t, Sony PCG-505TX
*
********************************************************************/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -44,11 +45,16 @@
#include <linux/malloc.h>
#include <linux/init.h>
#include <linux/rtnetlink.h>
+#include <linux/serial_reg.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/byteorder.h>
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+#endif
+
#include <net/irda/wrapper.h>
#include <net/irda/irda.h>
#include <net/irda/irmod.h>
@@ -62,10 +68,10 @@ static char *driver_name = "smc-ircc";
#define CHIP_IO_EXTENT 8
-static unsigned int io[] = { 0x2e8, 0x140, 0x118, 0x240 };
-static unsigned int io2[] = { 0x2f8, 0x3e8, 0x2e8, 0x3e8 };
+static unsigned int io[] = { ~0, ~0 };
+static unsigned int io2[] = { 0, 0 };
-static struct ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL};
+static struct ircc_cb *dev_self[] = { NULL, NULL};
/* Some prototypes */
static int ircc_open(int i, unsigned int iobase, unsigned int board_addr);
@@ -73,17 +79,30 @@ static int ircc_open(int i, unsigned int iobase, unsigned int board_addr);
static int ircc_close(struct ircc_cb *self);
#endif /* MODULE */
static int ircc_probe(int iobase, int board_addr);
-static int ircc_probe_smc(int *ioaddr, int *ioaddr2);
-static int ircc_dma_receive(struct ircc_cb *self);
-static int ircc_dma_receive_complete(struct ircc_cb *self, int iobase);
+static int ircc_probe_58(smc_chip_t *chip, chipio_t *info);
+static int ircc_probe_69(smc_chip_t *chip, chipio_t *info);
+static int ircc_dma_receive(struct ircc_cb *self, int iobase);
+static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase);
static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev);
-static void ircc_dma_xmit(struct ircc_cb *self, int iobase);
+static void ircc_dma_xmit(struct ircc_cb *self, int iobase, int bofs);
static void ircc_change_speed(void *priv, __u32 speed);
static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int ircc_is_receiving(struct ircc_cb *self);
static int ircc_net_open(struct net_device *dev);
static int ircc_net_close(struct net_device *dev);
+#ifdef CONFIG_APM
+static int ircc_apmproc(apm_event_t event);
+#endif /* CONFIG_APM */
+
+/* These are the currently known SMC chipsets */
+static smc_chip_t chips[] =
+{
+ { "FDC37C669", 0x55, 0x55, 0x0d, 0x04, ircc_probe_69 },
+ { "FDC37N869", 0x55, 0x00, 0x0d, 0x29, ircc_probe_69 },
+ { "FDC37N958", 0x55, 0x55, 0x20, 0x09, ircc_probe_58 },
+ { NULL }
+};
static int ircc_irq=255;
static int ircc_dma=255;
@@ -102,26 +121,38 @@ static inline void register_bank(int iobase, int bank)
*/
int __init ircc_init(void)
{
- int ioaddr, ioaddr2;
+ static int smcreg[] = { 0x3f0, 0x370 };
+ smc_chip_t *chip;
+ chipio_t info;
+ int ret = -ENODEV;
int i;
IRDA_DEBUG(0, __FUNCTION__ "\n");
- for (i=0; (io[i] < 2000) && (i < 4); i++) {
- int ioaddr = io[i];
- if (check_region(ioaddr, CHIP_IO_EXTENT))
- continue;
- if (ircc_open(i, io[i], io2[i]) == 0)
- return 0;
- }
- /* last chance saloon, see what the controller says */
- if (ircc_probe_smc(&ioaddr, &ioaddr2) == 0) {
- if (check_region(ioaddr, CHIP_IO_EXTENT) == 0)
- if (ircc_open(0, ioaddr, ioaddr2) == 0)
- return 0;
+ /* Probe for all the NSC chipsets we know about */
+ for (chip=chips; chip->name ; chip++,i++) {
+ for (i=0; i<2; i++) {
+ info.cfg_base = smcreg[i];
+
+ /*
+ * First we check if the user has supplied any
+ * parameters which we should use instead of probed
+ * values
+ */
+ if (io[i] < 2000) {
+ info.fir_base = io[i];
+ info.sir_base = io2[i];
+ } else if (chip->probe(chip, &info) < 0)
+ continue;
+ if (check_region(info.fir_base, CHIP_IO_EXTENT) < 0)
+ continue;
+ if (check_region(info.sir_base, CHIP_IO_EXTENT) < 0)
+ continue;
+ if (ircc_open(i, info.fir_base, info.sir_base) == 0)
+ ret = 0;
+ }
}
-
- return -ENODEV;
+ return ret;
}
/*
@@ -137,7 +168,7 @@ static void ircc_cleanup(void)
IRDA_DEBUG(0, __FUNCTION__ "\n");
- for (i=0; i < 4; i++) {
+ for (i=0; i < 2; i++) {
if (dev_self[i])
ircc_close(dev_self[i]);
}
@@ -150,7 +181,7 @@ static void ircc_cleanup(void)
* Open driver instance
*
*/
-static int ircc_open(int i, unsigned int iobase, unsigned int iobase2)
+static int ircc_open(int i, unsigned int fir_base, unsigned int sir_base)
{
struct ircc_cb *self;
struct irport_cb *irport;
@@ -159,9 +190,9 @@ static int ircc_open(int i, unsigned int iobase, unsigned int iobase2)
IRDA_DEBUG(0, __FUNCTION__ "\n");
- if ((config = ircc_probe(iobase, iobase2)) == -1) {
+ if ((config = ircc_probe(fir_base, sir_base)) == -1) {
IRDA_DEBUG(0, __FUNCTION__
- "(), addr 0x%04x - no device found!\n", iobase);
+ "(), addr 0x%04x - no device found!\n", fir_base);
return -1;
}
@@ -180,7 +211,7 @@ static int ircc_open(int i, unsigned int iobase, unsigned int iobase2)
/* Need to store self somewhere */
dev_self[i] = self;
- irport = irport_open(0, iobase2, config >> 4 & 0x0f);
+ irport = irport_open(i, sir_base, config >> 4 & 0x0f);
if (!irport)
return -ENODEV;
@@ -190,34 +221,32 @@ static int ircc_open(int i, unsigned int iobase, unsigned int iobase2)
irport->priv = self;
/* Initialize IO */
- self->io.iobase = iobase;
- self->io.iobase2 = iobase2; /* Used by irport */
+ self->io.fir_base = fir_base;
+ self->io.sir_base = sir_base; /* Used by irport */
self->io.irq = config >> 4 & 0x0f;
if (ircc_irq < 255) {
MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
driver_name, self->io.irq, ircc_irq);
self->io.irq = ircc_irq;
}
- self->io.io_ext = CHIP_IO_EXTENT;
- self->io.io_ext2 = 8; /* Used by irport */
+ self->io.fir_ext = CHIP_IO_EXTENT;
+ self->io.sir_ext = 8; /* Used by irport */
self->io.dma = config & 0x0f;
if (ircc_dma < 255) {
MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
driver_name, self->io.dma, ircc_dma);
self->io.dma = ircc_dma;
}
- self->io.fifo_size = 16;
/* Lock the port that we need */
- ret = check_region(self->io.iobase, self->io.io_ext);
+ ret = check_region(self->io.fir_base, self->io.fir_ext);
if (ret < 0) {
- IRDA_DEBUG(0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
- self->io.iobase);
- /* ircc_cleanup(self->self); */
+ IRDA_DEBUG(0, __FUNCTION__ ": can't get fir_base of 0x%03x\n",
+ self->io.fir_base);
+ kfree(self);
return -ENODEV;
}
-
- request_region(self->io.iobase, self->io.io_ext, driver_name);
+ request_region(self->io.fir_base, self->io.fir_ext, driver_name);
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&irport->qos);
@@ -229,7 +258,7 @@ static int ircc_open(int i, unsigned int iobase, unsigned int iobase2)
irport->qos.min_turn_time.bits = 0x07;
irda_qos_bits_to_value(&irport->qos);
- irport->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO;
+ irport->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
self->rx_buff.truesize = 4000;
@@ -256,6 +285,7 @@ static int ircc_open(int i, unsigned int iobase, unsigned int iobase2)
/* Override the speed change function, since we must control it now */
irport->change_speed = &ircc_change_speed;
+ irport->interrupt = &ircc_interrupt;
self->netdev->open = &ircc_net_open;
self->netdev->stop = &ircc_net_close;
@@ -279,23 +309,26 @@ static int ircc_close(struct ircc_cb *self)
ASSERT(self != NULL, return -1;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
irport_close(self->irport);
+ /* Stop interrupts */
register_bank(iobase, 0);
outb(0, iobase+IRCC_IER);
outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
-
+ outb(0x00, iobase+IRCC_MASTER);
+#if 0
+ /* Reset to SIR mode */
register_bank(iobase, 1);
-
outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase+IRCC_SCE_CFGA);
outb(IRCC_CFGB_IR, iobase+IRCC_SCE_CFGB);
-
+#endif
/* Release the PORT that this driver is using */
- IRDA_DEBUG(0, __FUNCTION__ "(), releasing 0x%03x\n", self->io.iobase);
+ IRDA_DEBUG(0, __FUNCTION__ "(), releasing 0x%03x\n",
+ self->io.fir_base);
- release_region(self->io.iobase, self->io.io_ext);
+ release_region(self->io.fir_base, self->io.fir_ext);
if (self->tx_buff.head)
kfree(self->tx_buff.head);
@@ -310,58 +343,106 @@ static int ircc_close(struct ircc_cb *self)
#endif /* MODULE */
/*
- * Function ircc_probe_smc (ioaddr, ioaddr2)
+ * Function ircc_probe_69 (chip, info)
*
- * Probe the SMC Chip for an IrDA port
+ * Probes for the SMC FDC37C669 and FDC37N869
*
*/
-static int ircc_probe_smc(int *ioaddr, int *ioaddr2)
+static int ircc_probe_69(smc_chip_t *chip, chipio_t *info)
{
- static int smcreg[] = { 0x3f0, 0x370 };
+ int cfg_base = info->cfg_base;
__u8 devid, mode;
- __u8 conf_reg;
- int ret = -1;
+ int ret = -ENODEV;
int fir_io;
- int i;
IRDA_DEBUG(0, __FUNCTION__ "()\n");
- for (i = 0; i < 2 && ret == -1; i++) {
- conf_reg = smcreg[i];
-
- /* Enter configuration */
- outb(0x55, conf_reg);
- outb(0x55, conf_reg);
-
- outb(0x0d, conf_reg);
- devid = inb(conf_reg+1);
- IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
+ /* Enter configuration */
+ outb(chip->entr1, cfg_base);
+ outb(chip->entr2, cfg_base);
+
+ outb(chip->cid_index, cfg_base);
+ devid = inb(cfg_base+1);
+ IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
+
+ /* Check for expected device ID; are there others? */
+ if (devid == chip->cid_value) {
+ outb(0x0c, cfg_base);
+ mode = inb(cfg_base+1);
+ mode = (mode & 0x38) >> 3;
- /* Check for expected device ID; are there others? */
- if (devid == 0x29) {
- outb(0x0c, conf_reg);
- mode = inb(conf_reg+1);
- mode = (mode & 0x38) >> 3;
-
- /* Value for IR port */
- if (mode && mode < 4) {
- /* SIR iobase */
- outb(0x25, conf_reg);
- *ioaddr2 = inb(conf_reg+1) << 2;
-
- /* FIR iobase */
- outb(0x2b, conf_reg);
- fir_io = inb(conf_reg+1) << 3;
- if (fir_io) {
- ret = 0;
- *ioaddr = fir_io;
- }
+ /* Value for IR port */
+ if (mode && mode < 4) {
+ /* SIR iobase */
+ outb(0x25, cfg_base);
+ info->sir_base = inb(cfg_base+1) << 2;
+
+ /* FIR iobase */
+ outb(0x2b, cfg_base);
+ fir_io = inb(cfg_base+1) << 3;
+ if (fir_io) {
+ ret = 0;
+ info->fir_base = fir_io;
}
}
+ }
+
+ /* Exit configuration */
+ outb(0xaa, cfg_base);
+
+ return ret;
+}
+
+/*
+ * Function ircc_probe_58 (chip, info)
+ *
+ * Probes for the SMC FDC37N958
+ *
+ */
+static int ircc_probe_58(smc_chip_t *chip, chipio_t *info)
+{
+ int cfg_base = info->cfg_base;
+ __u8 devid;
+ int ret = -ENODEV;
+ int fir_io;
+
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+ /* Enter configuration */
+ outb(chip->entr1, cfg_base);
+ outb(chip->entr2, cfg_base);
+
+ outb(chip->cid_index, cfg_base);
+ devid = inb(cfg_base+1);
+ IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
+
+ /* Check for expected device ID; are there others? */
+ if (devid == chip->cid_value) {
+ /* Select logical device (UART2) */
+ outb(0x07, cfg_base);
+ outb(0x05, cfg_base + 1);
+
+ /* SIR iobase */
+ outb(0x60, cfg_base);
+ info->sir_base = inb(cfg_base + 1) << 8;
+ outb(0x61, cfg_base);
+ info->sir_base |= inb(cfg_base + 1);
+
+ /* Read FIR base */
+ outb(0x62, cfg_base);
+ fir_io = inb(cfg_base + 1) << 8;
+ outb(0x63, cfg_base);
+ fir_io |= inb(cfg_base + 1);
+ outb(0x2b, cfg_base);
+ if (fir_io) {
+ ret = 0;
+ info->fir_base = fir_io;
+ }
+ }
+
+ /* Exit configuration */
+ outb(0xaa, cfg_base);
- /* Exit configuration */
- outb(0xaa, conf_reg);
- }
return ret;
}
@@ -371,34 +452,32 @@ static int ircc_probe_smc(int *ioaddr, int *ioaddr2)
* Returns non-negative on success.
*
*/
-static int ircc_probe(int iobase, int iobase2)
+static int ircc_probe(int fir_base, int sir_base)
{
- int version = 1;
int low, high, chip, config, dma, irq;
-
- IRDA_DEBUG(0, __FUNCTION__ "\n");
+ int iobase = fir_base;
+ int version = 1;
- /* Power on device */
- outb(inb(iobase+IRCC_MASTER) & ~IRCC_MASTER_POWERDOWN,
- iobase+IRCC_MASTER);
+ IRDA_DEBUG(0, __FUNCTION__ "\n");
register_bank(iobase, 3);
- high = inb(iobase+IRCC_ID_HIGH);
- low = inb(iobase+IRCC_ID_LOW);
- chip = inb(iobase+IRCC_CHIP_ID);
+ high = inb(iobase+IRCC_ID_HIGH);
+ low = inb(iobase+IRCC_ID_LOW);
+ chip = inb(iobase+IRCC_CHIP_ID);
version = inb(iobase+IRCC_VERSION);
- config = inb(iobase+IRCC_INTERFACE);
- irq = config >> 4 & 0x0f;
- dma = config & 0x0f;
+ config = inb(iobase+IRCC_INTERFACE);
+ irq = config >> 4 & 0x0f;
+ dma = config & 0x0f;
if (high == 0x10 && low == 0xb8 && (chip == 0xf1 || chip == 0xf2)) {
- IRDA_DEBUG(0, "SMC IrDA Controller found; IrCC version %d.%d, "
- "port 0x%04x, dma %d, interrupt %d\n",
- chip & 0x0f, version, iobase, dma, irq);
+ MESSAGE("SMC IrDA Controller found; IrCC version %d.%d, "
+ "port 0x%03x, dma=%d, irq=%d\n",
+ chip & 0x0f, version, iobase, dma, irq);
} else
- return -1;
+ return -ENODEV;
- outb(0, iobase+IRCC_MASTER);
+ /* Power on device */
+ outb(0x00, iobase+IRCC_MASTER);
return config;
}
@@ -411,7 +490,7 @@ static int ircc_probe(int iobase, int iobase2)
*/
static void ircc_change_speed(void *priv, __u32 speed)
{
- int iobase, ir_mode, select, fast;
+ int iobase, ir_mode, ctrl, fast;
struct ircc_cb *self = (struct ircc_cb *) priv;
struct net_device *dev;
@@ -420,49 +499,39 @@ static void ircc_change_speed(void *priv, __u32 speed)
ASSERT(self != NULL, return;);
dev = self->netdev;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Update accounting for new speed */
self->io.speed = speed;
+ outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
+ outb(0x00, iobase+IRCC_MASTER);
+
switch (speed) {
case 9600:
case 19200:
case 38400:
case 57600:
- case 115200:
- IRDA_DEBUG(0, __FUNCTION__
- "(), using irport to change speed to %d\n", speed);
-
- register_bank(iobase, 0);
- outb(0, iobase+IRCC_IER);
- outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
- outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
-
- dev->hard_start_xmit = &irport_hard_xmit;
-
- /* We must give the interrupt back to irport */
- self->irport->interrupt = irport_interrupt;
-
- irport_start(self->irport);
- irport_change_speed(self->irport, speed);
- return;
+ case 115200:
+ ir_mode = IRCC_CFGA_IRDA_SIR_A;
+ ctrl = 0;
+ fast = 0;
break;
case 576000:
ir_mode = IRCC_CFGA_IRDA_HDLC;
- select = 0;
+ ctrl = IRCC_CRC;
fast = 0;
IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
break;
case 1152000:
ir_mode = IRCC_CFGA_IRDA_HDLC;
- select = IRCC_1152;
+ ctrl = IRCC_1152 | IRCC_CRC;
fast = 0;
IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
break;
case 4000000:
ir_mode = IRCC_CFGA_IRDA_4PPM;
- select = 0;
+ ctrl = IRCC_CRC;
fast = IRCC_LCR_A_FAST;
IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
break;
@@ -471,39 +540,55 @@ static void ircc_change_speed(void *priv, __u32 speed)
speed);
return;
}
-
- outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
-
+
register_bank(iobase, 0);
outb(0, iobase+IRCC_IER);
-
- irport_stop(self->irport);
+ outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
+
+ /* Make special FIR init if necessary */
+ if (speed > 115200) {
+ irport_stop(self->irport);
- /* Install FIR transmit handler */
- dev->hard_start_xmit = &ircc_hard_xmit;
+ /* Install FIR transmit handler */
+ dev->hard_start_xmit = &ircc_hard_xmit;
- /* Need to steal the interrupt as well */
- self->irport->interrupt = &ircc_interrupt;
+ /*
+ * Don't know why we have to do this, but FIR interrupts
+ * stops working if we remove it.
+ */
+ /* outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR); */
+ /* Be ready for incomming frames */
+ ircc_dma_receive(self, iobase);
+ } else {
+ /* Install SIR transmit handler */
+ dev->hard_start_xmit = &irport_hard_xmit;
+ irport_start(self->irport);
+
+ IRDA_DEBUG(0, __FUNCTION__
+ "(), using irport to change speed to %d\n", speed);
+ irport_change_speed(self->irport, speed);
+ }
dev->tbusy = 0;
-
+
register_bank(iobase, 1);
outb(((inb(iobase+IRCC_SCE_CFGA) & 0x87) | ir_mode),
iobase+IRCC_SCE_CFGA);
-
- outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_IR),
- iobase+IRCC_SCE_CFGB);
+#ifdef SMC_669 /* Uses pin 88/89 for Rx/Tx */
+ outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),
+ iobase+IRCC_SCE_CFGB);
+#else
+ outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
+ iobase+IRCC_SCE_CFGB);
+#endif
(void) inb(iobase+IRCC_FIFO_THRESHOLD);
outb(64, iobase+IRCC_FIFO_THRESHOLD);
-
+
register_bank(iobase, 4);
-
- outb((inb(iobase+IRCC_CONTROL) & 0x30) | select | IRCC_CRC,
- iobase+IRCC_CONTROL);
-
+ outb((inb(iobase+IRCC_CONTROL) & 0x30) | ctrl, iobase+IRCC_CONTROL);
+
register_bank(iobase, 0);
-
outb(fast, iobase+IRCC_LCR_A);
}
@@ -517,21 +602,20 @@ static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct irport_cb *irport;
struct ircc_cb *self;
+ unsigned long flags;
+ __u32 speed;
int iobase;
int mtt;
- __u32 speed;
irport = (struct irport_cb *) dev->priv;
self = (struct ircc_cb *) irport->priv;
-
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
- IRDA_DEBUG(2, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies,
- (int) skb->len);
+ spin_lock_irqsave(&self->lock, flags);
- /* Check if we need to change the speed */
+ /* Check if we need to change the speed after this frame */
if ((speed = irda_get_speed(skb)) != self->io.speed)
self->new_speed = speed;
@@ -541,19 +625,28 @@ static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
memcpy(self->tx_buff.head, skb->data, skb->len);
- /* Make sure that the length is a multiple of 16 bits */
- if (skb->len & 0x01)
- skb->len++;
-
self->tx_buff.len = skb->len;
self->tx_buff.data = self->tx_buff.head;
mtt = irda_get_mtt(skb);
- if (mtt)
- udelay(mtt);
-
- ircc_dma_xmit(self, iobase);
+ if (mtt) {
+ int bofs;
+
+ /*
+ * Compute who many BOFS (STA or PA's) we need to waste the
+ * min turn time given the speed of the link.
+ */
+ bofs = mtt * (self->io.speed / 1000) / 8000;
+ if (bofs > 4095)
+ bofs = 4095;
+
+ ircc_dma_xmit(self, iobase, bofs);
+ } else {
+ /* Transmit frame */
+ ircc_dma_xmit(self, iobase, 0);
+ }
+ spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
return 0;
@@ -565,44 +658,49 @@ static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
* Transmit data using DMA
*
*/
-static void ircc_dma_xmit(struct ircc_cb *self, int iobase)
+static void ircc_dma_xmit(struct ircc_cb *self, int iobase, int bofs)
{
- IRDA_DEBUG(2, __FUNCTION__ "\n");
+ __u8 ctrl;
- ASSERT(self != NULL, return;);
-
- iobase = self->io.iobase;
+ IRDA_DEBUG(2, __FUNCTION__ "\n");
+#if 0
+ /* Disable Rx */
+ register_bank(iobase, 0);
+ outb(0x00, iobase+IRCC_LCR_B);
+#endif
+ register_bank(iobase, 1);
+ outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ iobase+IRCC_SCE_CFGB);
- setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len,
- DMA_TX_MODE);
-
self->io.direction = IO_XMIT;
- outb(0x08, self->io.iobase2+4);
-
+ /* Set BOF additional count for generating the min turn time */
register_bank(iobase, 4);
- outb((inb(iobase+IRCC_CONTROL) & 0xf0), iobase+IRCC_CONTROL);
-
- outb(2, iobase+IRCC_BOF_COUNT_LO);
- outb(0, iobase+IRCC_BRICKWALL_CNT_LO);
-#if 1
- outb(self->tx_buff.len >> 8, iobase+IRCC_BRICKWALL_TX_CNT_HI);
+ outb(bofs & 0xff, iobase+IRCC_BOF_COUNT_LO);
+ ctrl = inb(iobase+IRCC_CONTROL) & 0xf0;
+ outb(ctrl | ((bofs >> 8) & 0x0f), iobase+IRCC_BOF_COUNT_HI);
+
+ /* Set max Tx frame size */
+ outb(self->tx_buff.len >> 8, iobase+IRCC_TX_SIZE_HI);
outb(self->tx_buff.len & 0xff, iobase+IRCC_TX_SIZE_LO);
-#else
- outb(0, iobase+IRCC_BRICKWALL_TX_CNT_HI);
- outb(0, iobase+IRCC_TX_SIZE_LO);
-#endif
+ /* Setup DMA controller (must be done after enabling chip DMA) */
+ setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len,
+ DMA_TX_MODE);
+
+ outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR);
+ /* Enable burst mode chip Tx DMA */
register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE,
- iobase+IRCC_SCE_CFGB);
+ outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
+ IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
+ /* Enable interrupt */
+ outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
register_bank(iobase, 0);
-
outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER);
- outb(IRCC_LCR_B_SCE_TRANSMIT|IRCC_LCR_B_SIP_ENABLE, iobase+IRCC_LCR_B);
- outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
+ /* Enable transmit */
+ outb(IRCC_LCR_B_SCE_TRANSMIT|IRCC_LCR_B_SIP_ENABLE, iobase+IRCC_LCR_B);
}
/*
@@ -612,39 +710,36 @@ static void ircc_dma_xmit(struct ircc_cb *self, int iobase)
* by the interrupt handler
*
*/
-static void ircc_dma_xmit_complete(struct ircc_cb *self, int underrun)
+static void ircc_dma_xmit_complete(struct ircc_cb *self, int iobase)
{
- int iobase, d;
-
IRDA_DEBUG(2, __FUNCTION__ "\n");
-
- ASSERT(self != NULL, return;);
-
- register_bank(self->io.iobase, 1);
-
- outb(inb(self->io.iobase+IRCC_SCE_CFGB) & IRCC_CFGB_DMA_ENABLE,
- self->io.iobase+IRCC_SCE_CFGB);
-
- d = get_dma_residue(self->io.dma);
-
- IRDA_DEBUG(0, __FUNCTION__
- ": dma residue = %d, len=%d, sent=%d\n",
- d, self->tx_buff.len, self->tx_buff.len - d);
-
- iobase = self->io.iobase;
+#if 0
+ /* Disable Tx */
+ register_bank(iobase, 0);
+ outb(0x00, iobase+IRCC_LCR_B);
+#endif
+ register_bank(self->io.fir_base, 1);
+ outb(inb(self->io.fir_base+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ self->io.fir_base+IRCC_SCE_CFGB);
/* Check for underrrun! */
- if (underrun) {
+ register_bank(iobase, 0);
+ if (inb(iobase+IRCC_LSR) & IRCC_LSR_UNDERRUN) {
self->irport->stats.tx_errors++;
- self->irport->stats.tx_fifo_errors++;
+ self->irport->stats.tx_fifo_errors++;
+
+ /* Reset error condition */
+ register_bank(iobase, 0);
+ outb(IRCC_MASTER_ERROR_RESET, iobase+IRCC_MASTER);
+ outb(0x00, iobase+IRCC_MASTER);
} else {
self->irport->stats.tx_packets++;
self->irport->stats.tx_bytes += self->tx_buff.len;
}
+ /* Check if it's time to change the speed */
if (self->new_speed) {
- ircc_change_speed(self, self->new_speed);
-
+ ircc_change_speed(self, self->new_speed);
self->new_speed = 0;
}
@@ -662,39 +757,31 @@ static void ircc_dma_xmit_complete(struct ircc_cb *self, int underrun)
* if it starts to receive a frame.
*
*/
-static int ircc_dma_receive(struct ircc_cb *self)
-{
- int iobase;
-
- IRDA_DEBUG(2, __FUNCTION__ "\n");
-
- ASSERT(self != NULL, return -1;);
-
- iobase= self->io.iobase;
+static int ircc_dma_receive(struct ircc_cb *self, int iobase)
+{
+ /* Turn off chip DMA */
+ //register_bank(iobase, 1);
+ //outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ // iobase+IRCC_SCE_CFGB);
setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize,
- DMA_RX_MODE);
-
- /* driver->media_busy = FALSE; */
+ DMA_RX_MODE);
+ /* Set max Rx frame size */
+ register_bank(iobase, 4);
+ outb((2050 >> 8) & 0x0f, iobase+IRCC_RX_SIZE_HI);
+ outb(2050 & 0xff, iobase+IRCC_RX_SIZE_LO);
+
self->io.direction = IO_RECV;
self->rx_buff.data = self->rx_buff.head;
-#if 0
- self->rx_buff.offset = 0;
-#endif
-
- register_bank(iobase, 4);
- outb(inb(iobase+IRCC_CONTROL) & 0xf0, iobase+IRCC_CONTROL);
- outb(2, iobase+IRCC_BOF_COUNT_LO);
- outb(0, iobase+IRCC_BRICKWALL_CNT_LO);
- outb(0, iobase+IRCC_BRICKWALL_TX_CNT_HI);
- outb(0, iobase+IRCC_TX_SIZE_LO);
- outb(0, iobase+IRCC_RX_SIZE_HI);
- outb(0, iobase+IRCC_RX_SIZE_LO);
+ /* Setup DMA controller */
+
+ /* Enable receiver */
register_bank(iobase, 0);
outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE,
iobase+IRCC_LCR_B);
+ /* Enable burst mode chip Rx DMA */
register_bank(iobase, 1);
outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
@@ -709,45 +796,54 @@ static int ircc_dma_receive(struct ircc_cb *self)
*
*
*/
-static int ircc_dma_receive_complete(struct ircc_cb *self, int iobase)
+static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase)
{
+ unsigned long flags;
struct sk_buff *skb;
int len, msgcnt;
IRDA_DEBUG(2, __FUNCTION__ "\n");
+#if 0
+ /* Disable Rx */
+ register_bank(iobase, 0);
+ outb(0x00, iobase+IRCC_LCR_B);
+#endif
+ register_bank(iobase, 0);
+ msgcnt = inb(iobase+IRCC_LCR_B) & 0x08;
- msgcnt = inb(self->io.iobase+IRCC_LCR_B) & 0x08;
-
- IRDA_DEBUG(0, __FUNCTION__ ": dma count = %d\n",
+ IRDA_DEBUG(2, __FUNCTION__ ": dma count = %d\n",
get_dma_residue(self->io.dma));
- len = self->rx_buff.truesize - get_dma_residue(self->io.dma) - 4;
-
- IRDA_DEBUG(0, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
+ len = self->rx_buff.truesize - get_dma_residue(self->io.dma);
+
+ /* Remove CRC */
+ if (self->io.speed < 4000000)
+ len -= 2;
+ else
+ len -= 4;
+
+ if ((len < 2) && (len > 2050)) {
+ WARNING(__FUNCTION__ "(), bogus len=%d\n", len);
+ return;
+ }
+ IRDA_DEBUG(2, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
skb = dev_alloc_skb(len+1);
if (!skb) {
WARNING(__FUNCTION__ "(), memory squeeze, dropping frame.\n");
- return FALSE;
- }
-
+ return;
+ }
/* Make sure IP header gets aligned */
skb_reserve(skb, 1);
- skb_put(skb, len);
- memcpy(skb->data, self->rx_buff.data, len);
+ memcpy(skb_put(skb, len), self->rx_buff.data, len);
self->irport->stats.rx_packets++;
+ self->irport->stats.rx_bytes += len;
skb->dev = self->netdev;
skb->mac.raw = skb->data;
skb->protocol = htons(ETH_P_IRDA);
netif_rx(skb);
-
- register_bank(self->io.iobase, 1);
- outb(inb(self->io.iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
- self->io.iobase+IRCC_SCE_CFGB);
-
- return TRUE;
}
/*
@@ -758,58 +854,54 @@ static int ircc_dma_receive_complete(struct ircc_cb *self, int iobase)
*/
static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- int iobase, iir;
struct net_device *dev = (struct net_device *) dev_id;
+ struct irport_cb *irport;
struct ircc_cb *self;
+ int iobase, iir;
if (dev == NULL) {
printk(KERN_WARNING "%s: irq %d for unknown device.\n",
driver_name, irq);
return;
}
-
- self = (struct ircc_cb *) dev->priv;
+ irport = (struct irport_cb *) dev->priv;
+ ASSERT(irport != NULL, return;);
+ self = (struct ircc_cb *) irport->priv;
+ ASSERT(self != NULL, return;);
- iobase = self->io.iobase;
+ /* Check if we should use the SIR interrupt handler */
+ if (self->io.speed < 576000) {
+ irport_interrupt(irq, dev_id, regs);
+ return;
+ }
+ iobase = self->io.fir_base;
+ spin_lock(&self->lock);
dev->interrupt = 1;
- outb(0, iobase+IRCC_MASTER);
-
register_bank(iobase, 0);
iir = inb(iobase+IRCC_IIR);
/* Disable interrupts */
outb(0, iobase+IRCC_IER);
- IRDA_DEBUG(0, __FUNCTION__ "(), iir = 0x%02x\n", iir);
+ IRDA_DEBUG(2, __FUNCTION__ "(), iir = 0x%02x\n", iir);
if (iir & IRCC_IIR_EOM) {
- IRDA_DEBUG(0, __FUNCTION__ "(), IRCC_IIR_EOM\n");
-
if (self->io.direction == IO_RECV)
ircc_dma_receive_complete(self, iobase);
else
ircc_dma_xmit_complete(self, iobase);
- ircc_dma_receive(self);
- }
- if (iir & IRCC_IIR_ACTIVE_FRAME) {
- IRDA_DEBUG(0, __FUNCTION__ "(), IRCC_IIR_ACTIVE_FRAME\n");
- self->rx_buff.state = INSIDE_FRAME;
-#if 0
- ircc_dma_receive(self);
-#endif
- }
- if (iir & IRCC_IIR_RAW_MODE) {
- IRDA_DEBUG(0, __FUNCTION__ "(), IIR RAW mode interrupt.\n");
+ ircc_dma_receive(self, iobase);
}
+ /* Enable interrupts again */
register_bank(iobase, 0);
outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER);
- outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
dev->interrupt = 0;
+ spin_unlock(&self->lock);
}
/*
@@ -855,7 +947,7 @@ static int ircc_net_open(struct net_device *dev)
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
irport_net_open(dev); /* irport allocates the irq */
@@ -894,7 +986,7 @@ static int ircc_net_close(struct net_device *dev)
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
irport_net_close(dev);
@@ -907,6 +999,69 @@ static int ircc_net_close(struct net_device *dev)
return 0;
}
+#ifdef CONFIG_APM
+static void ircc_suspend(struct ircc_cb *self)
+{
+ int i = 10;
+
+ MESSAGE("%s, Suspending\n", driver_name);
+
+ if (self->io.suspended)
+ return;
+
+ ircc_net_close(self->netdev);
+
+ self->io.suspended = 1;
+}
+
+static void ircc_wakeup(struct ircc_cb *self)
+{
+ struct net_device *dev = self->netdev;
+ unsigned long flags;
+
+ if (!self->io.suspended)
+ return;
+
+ save_flags(flags);
+ cli();
+
+ ircc_net_open(self->netdev);
+
+ restore_flags(flags);
+ MESSAGE("%s, Waking up\n", driver_name);
+}
+
+static int ircc_apmproc(apm_event_t event)
+{
+ static int down = 0; /* Filter out double events */
+ int i;
+
+ switch (event) {
+ case APM_SYS_SUSPEND:
+ case APM_USER_SUSPEND:
+ if (!down) {
+ for (i=0; i<4; i++) {
+ if (dev_self[i])
+ ircc_suspend(dev_self[i]);
+ }
+ }
+ down = 1;
+ break;
+ case APM_NORMAL_RESUME:
+ case APM_CRITICAL_RESUME:
+ if (down) {
+ for (i=0; i<4; i++) {
+ if (dev_self[i])
+ ircc_wakeup(dev_self[i]);
+ }
+ }
+ down = 0;
+ break;
+ }
+ return 0;
+}
+#endif /* CONFIG_APM */
+
#ifdef MODULE
MODULE_AUTHOR("Thomas Davis <tadavis@jps.net>");
MODULE_DESCRIPTION("SMC IrCC controller driver");
diff --git a/drivers/net/irda/toshoboe.c b/drivers/net/irda/toshoboe.c
index cbf06af5f..a7b97af37 100644
--- a/drivers/net/irda/toshoboe.c
+++ b/drivers/net/irda/toshoboe.c
@@ -32,37 +32,6 @@
static char *rcsid = "$Id: toshoboe.c,v 1.91 1999/06/29 14:21:06 root Exp $";
-/*
- * $Log: toshoboe.c,v $
- * Revision 1.9 1999/06/29 14:21:06 root
- * *** empty log message ***
- *
- * Revision 1.8 1999/06/29 14:15:08 root
- * *** empty log message ***
- *
- * Revision 1.7 1999/06/29 13:46:42 root
- * *** empty log message ***
- *
- * Revision 1.6 1999/06/29 12:31:03 root
- * *** empty log message ***
- *
- * Revision 1.5 1999/05/12 12:24:39 root
- * *** empty log message ***
- *
- * Revision 1.4 1999/05/12 11:55:08 root
- * *** empty log message ***
- *
- * Revision 1.3 1999/05/09 01:33:12 root
- * *** empty log message ***
- *
- * Revision 1.2 1999/05/09 01:30:38 root
- * *** empty log message ***
- *
- * Revision 1.1 1999/05/09 01:25:04 root
- * Initial revision
- *
- */
-
/* Define this to have only one frame in the XMIT or RECV queue */
/* Toshiba's drivers do this, but it disables back to back tansfers */
/* I think that the chip may have some problems certainly, I have */
@@ -682,7 +651,7 @@ toshoboe_close (struct toshoboe_cb *self)
toshoboe_disablebm (self);
}
- release_region (self->io.iobase, self->io.io_ext);
+ release_region (self->io.sir_base, self->io.sir_ext);
for (i = 0; i < TX_SLOTS; ++i)
@@ -754,17 +723,17 @@ toshoboe_open (struct pci_dev *pci_dev)
self->pdev = pci_dev;
self->base = pci_dev->resource[0].start;
- self->io.iobase = self->base;
+ self->io.sir_base = self->base;
self->io.irq = pci_dev->irq;
- self->io.io_ext = CHIP_IO_EXTENT;
+ self->io.sir_ext = CHIP_IO_EXTENT;
self->io.speed = 9600;
/* Lock the port that we need */
- i = check_region (self->io.iobase, self->io.io_ext);
+ i = check_region (self->io.sir_base, self->io.sir_ext);
if (i < 0)
{
IRDA_DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- self->io.iobase);
+ self->io.sir_base);
dev_self[i] = NULL;
kfree (self);
@@ -864,13 +833,12 @@ toshoboe_open (struct pci_dev *pci_dev)
}
- request_region (self->io.iobase, self->io.io_ext, driver_name);
+ request_region (self->io.sir_base, self->io.sir_ext, driver_name);
if (!(dev = dev_alloc("irda%d", &err))) {
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
return -ENOMEM;
}
-
dev->priv = (void *) self;
self->netdev = dev;
@@ -1025,7 +993,7 @@ int __init toshoboe_init (void)
if (pci_dev)
{
printk (KERN_WARNING "ToshOboe: Found 701 chip at 0x%0lx irq %d\n",
- pci_dev->resource[0].start,
+ pci_dev->resource[0].start,
pci_dev->irq);
if (!toshoboe_open (pci_dev))
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 1bc2d9fa9..7f781719c 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Paul VanderSpek
* Created at: Wed Nov 4 11:46:16 1998
- * Modified at: Wed Jan 5 15:11:21 2000
+ * Modified at: Fri Jan 28 12:10:59 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
@@ -183,21 +183,21 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq,
dev_self[i] = self;
/* Initialize IO */
- self->io.iobase = iobase;
+ self->io.fir_base = iobase;
self->io.irq = irq;
- self->io.io_ext = CHIP_IO_EXTENT;
+ self->io.fir_ext = CHIP_IO_EXTENT;
self->io.dma = dma;
self->io.fifo_size = 32;
/* Lock the port that we need */
- ret = check_region(self->io.iobase, self->io.io_ext);
+ ret = check_region(self->io.fir_base, self->io.fir_ext);
if (ret < 0) {
IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- self->io.iobase);
+ self->io.fir_base);
/* w83977af_cleanup( self); */
return -ENODEV;
}
- request_region(self->io.iobase, self->io.io_ext, driver_name);
+ request_region(self->io.fir_base, self->io.fir_ext, driver_name);
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&self->qos);
@@ -243,9 +243,6 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq,
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
return -ENOMEM;
}
- /* dev_alloc doesn't clear the struct, so lets do a little hack */
- memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
-
dev->priv = (void *) self;
self->netdev = dev;
@@ -282,7 +279,7 @@ static int w83977af_close(struct w83977af_ir *self)
IRDA_DEBUG(0, __FUNCTION__ "()\n");
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
#ifdef CONFIG_USE_W977_PNP
/* enter PnP configuration mode */
@@ -301,14 +298,12 @@ static int w83977af_close(struct w83977af_ir *self)
rtnl_lock();
unregister_netdevice(self->netdev);
rtnl_unlock();
- /* Must free the old-style 2.2.x device */
- kfree(self->netdev);
}
/* Release the PORT that this driver is using */
IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n",
- self->io.iobase);
- release_region(self->io.iobase, self->io.io_ext);
+ self->io.fir_base);
+ release_region(self->io.fir_base, self->io.fir_ext);
if (self->tx_buff.head)
kfree(self->tx_buff.head);
@@ -426,7 +421,7 @@ void w83977af_change_speed(struct w83977af_ir *self, __u32 speed)
int iobase;
__u8 set;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Update accounting for new speed */
self->io.speed = speed;
@@ -510,7 +505,7 @@ int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self = (struct w83977af_ir *) dev->priv;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies,
(int) skb->len);
@@ -692,7 +687,7 @@ void w83977af_dma_xmit_complete(struct w83977af_ir *self)
ASSERT(self != NULL, return;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Save current set */
set = inb(iobase+SSR);
@@ -748,7 +743,7 @@ int w83977af_dma_receive(struct w83977af_ir *self)
IRDA_DEBUG(4, __FUNCTION__ "\n");
- iobase= self->io.iobase;
+ iobase= self->io.fir_base;
/* Save current set */
set = inb(iobase+SSR);
@@ -822,12 +817,12 @@ int w83977af_dma_receive_complete(struct w83977af_ir *self)
st_fifo = &self->st_fifo;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Save current set */
set = inb(iobase+SSR);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Read status FIFO */
switch_bank(iobase, SET5);
@@ -948,7 +943,7 @@ static void w83977af_pio_receive(struct w83977af_ir *self)
ASSERT(self != NULL, return;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Receive all characters in Rx FIFO */
do {
@@ -973,11 +968,11 @@ static __u8 w83977af_sir_interrupt(struct w83977af_ir *self, int isr)
IRDA_DEBUG(4, __FUNCTION__ "(), isr=%#x\n", isr);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Transmit FIFO low on data */
if (isr & ISR_TXTH_I) {
/* Write data left in transmit buffer */
- actual = w83977af_pio_write(self->io.iobase,
+ actual = w83977af_pio_write(self->io.fir_base,
self->tx_buff.data,
self->tx_buff.len,
self->io.fifo_size);
@@ -1042,7 +1037,7 @@ static __u8 w83977af_fir_interrupt(struct w83977af_ir *self, int isr)
__u8 set;
int iobase;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
set = inb(iobase+SSR);
/* End of frame detected in FIFO */
@@ -1131,7 +1126,7 @@ static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs)
dev->interrupt = 1;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Save current bank */
set = inb(iobase+SSR);
@@ -1171,7 +1166,7 @@ static int w83977af_is_receiving(struct w83977af_ir *self)
ASSERT(self != NULL, return FALSE;);
if (self->io.speed > 115200) {
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Check if rx FIFO is not empty */
set = inb(iobase+SSR);
@@ -1225,7 +1220,7 @@ static int w83977af_net_open(struct net_device *dev)
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
if (request_irq(self->io.irq, w83977af_interrupt, 0, dev->name,
(void *) dev)) {
@@ -1290,7 +1285,7 @@ static int w83977af_net_close(struct net_device *dev)
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Stop device */
dev->tbusy = 1;
diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c
new file mode 100644
index 000000000..ce43ad752
--- /dev/null
+++ b/drivers/net/mac89x0.c
@@ -0,0 +1,678 @@
+/* cs89x0.c: A Crystal Semiconductor CS89[02]0 driver for linux. */
+/*
+ Written 1996 by Russell Nelson, with reference to skeleton.c
+ written 1993-1994 by Donald Becker.
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License, incorporated herein by reference.
+
+ The author may be reached at nelson@crynwr.com, Crynwr
+ Software, 11 Grant St., Potsdam, NY 13676
+
+ Changelog:
+
+ Mike Cruse : mcruse@cti-ltd.com
+ : 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
+ : driver prematurely.
+
+ Mike Cruse : Rewrote init_module() and cleanup_module using 8390.c
+ : as an example. Disabled autoprobing in init_module(),
+ : not a good thing to do to other devices while Linux
+ : is running from all accounts.
+
+ Alan Cox : Removed 1.2 support, added 2.1 extra counters.
+
+ David Huggins-Daines <dhd@debian.org>
+
+ Split this off into mac89x0.c, and gutted it of all parts which are
+ not relevant to the existing CS8900 cards on the Macintosh
+ (i.e. basically the Daynaport CS and LC cards). To be precise:
+
+ * Removed all the media-detection stuff, because these cards are
+ TP-only.
+
+ * Lobotomized the ISA interrupt bogosity, because these cards use
+ a hardwired NuBus interrupt and a magic ISAIRQ value in the card.
+
+ * Basically eliminated everything not relevant to getting the
+ cards minimally functioning on the Macintosh.
+
+ I might add that these cards are badly designed even from the Mac
+ standpoint, in that Dayna, in their infinite wisdom, used NuBus slot
+ I/O space and NuBus interrupts for these cards, but neglected to
+ provide anything even remotely resembling a NuBus ROM. Therefore we
+ have to probe for them in a brain-damaged ISA-like fashion.
+*/
+
+static char *version =
+"cs89x0.c:v1.02 11/26/96 Russell Nelson <nelson@crynwr.com>\n";
+
+/* ======================= configure the driver here ======================= */
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifndef NET_DEBUG
+#define NET_DEBUG 0
+#endif
+
+/* ======================= end of configuration ======================= */
+
+
+/* Always include 'config.h' first in case the user wants to turn on
+ or override something. */
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#define PRINTK(x) printk x
+
+/*
+ Sources:
+
+ Crynwr packet driver epktisa.
+
+ Crystal Semiconductor data sheets.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/nubus.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/hwtest.h>
+#include <asm/macints.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include "cs89x0.h"
+
+static unsigned int net_debug = NET_DEBUG;
+
+/* Information that need to be kept for each board. */
+struct net_local {
+ struct net_device_stats stats;
+ int chip_type; /* one of: CS8900, CS8920, CS8920M */
+ char chip_revision; /* revision letter of the chip ('A'...) */
+ int send_cmd; /* the propercommand used to send a packet. */
+ int rx_mode;
+ int curr_rx_cfg;
+ int send_underrun; /* keep track of how many underruns in a row we get */
+ struct sk_buff *skb;
+};
+
+/* Index to functions, as function prototypes. */
+
+extern int mac89x0_probe(struct net_device *dev);
+extern void reset_chip(struct net_device *dev);
+static int net_open(struct net_device *dev);
+static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void set_multicast_list(struct net_device *dev);
+static void net_rx(struct net_device *dev);
+static int net_close(struct net_device *dev);
+static struct net_device_stats *net_get_stats(struct net_device *dev);
+static int set_mac_address(struct net_device *dev, void *addr);
+
+
+/* Example routines you must write ;->. */
+#define tx_done(dev) 1
+
+/* For reading/writing registers ISA-style */
+static int inline
+readreg_io(struct net_device *dev, int portno)
+{
+ writew(swab16(portno), dev->base_addr + ADD_PORT);
+ return swab16(readw(dev->base_addr + DATA_PORT));
+}
+
+static void inline
+writereg_io(struct net_device *dev, int portno, int value)
+{
+ writew(swab16(portno), dev->base_addr + ADD_PORT);
+ writew(swab16(value), dev->base_addr + DATA_PORT);
+}
+
+/* These are for reading/writing registers in shared memory */
+static int inline
+readreg(struct net_device *dev, int portno)
+{
+ return swab16(readw(dev->mem_start + portno));
+}
+
+static void inline
+writereg(struct net_device *dev, int portno, int value)
+{
+ writew(swab16(value), dev->mem_start + portno);
+}
+
+/* Probe for the CS8900 card in slot E. We won't bother looking
+ anywhere else until we have a really good reason to do so. */
+int __init mac89x0_probe(struct net_device *dev)
+{
+ static int once_is_enough = 0;
+ struct net_local *lp;
+ static unsigned version_printed = 0;
+ int i, slot;
+ unsigned rev_type = 0;
+ unsigned long ioaddr;
+ unsigned short sig;
+
+ if (once_is_enough)
+ return ENODEV;
+ once_is_enough = 1;
+
+ /* We might have to parameterize this later */
+ slot = 0xE;
+ /* Get out now if there's a real NuBus card in slot E */
+ if (nubus_find_slot(slot, NULL) != NULL)
+ return ENODEV;
+
+ /* The pseudo-ISA bits always live at offset 0x300 (gee,
+ wonder why...) */
+ ioaddr = (unsigned long)
+ nubus_slot_addr(slot) | (((slot&0xf) << 20) + DEFAULTIOBASE);
+ {
+ unsigned long flags;
+ int card_present;
+
+ save_flags(flags);
+ cli();
+ card_present = hwreg_present((void*) ioaddr+4)
+ && hwreg_present((void*) ioaddr + DATA_PORT);
+ restore_flags(flags);
+
+ if (!card_present)
+ return ENODEV;
+ }
+
+ writew(0, ioaddr + ADD_PORT);
+ sig = readw(ioaddr + DATA_PORT);
+ if (sig != swab16(CHIP_EISA_ID_SIG))
+ return ENODEV;
+
+ /* Initialize the net_device structure. */
+ if (dev->priv == NULL) {
+ dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+ memset(dev->priv, 0, sizeof(struct net_local));
+ }
+ lp = (struct net_local *)dev->priv;
+
+ /* Fill in the 'dev' fields. */
+ dev->base_addr = ioaddr;
+ dev->mem_start = (unsigned long)
+ nubus_slot_addr(slot) | (((slot&0xf) << 20) + MMIOBASE);
+ dev->mem_end = dev->mem_start + 0x1000;
+
+ /* Turn on shared memory */
+ writereg_io(dev, PP_BusCTL, MEMORY_ON);
+
+ /* get the chip type */
+ rev_type = readreg(dev, PRODUCT_ID_ADD);
+ lp->chip_type = rev_type &~ REVISON_BITS;
+ lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
+
+ /* Check the chip type and revision in order to set the correct send command
+ CS8920 revision C and CS8900 revision F can use the faster send. */
+ lp->send_cmd = TX_AFTER_381;
+ if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')
+ lp->send_cmd = TX_NOW;
+ if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')
+ lp->send_cmd = TX_NOW;
+
+ if (net_debug && version_printed++ == 0)
+ printk(version);
+
+ printk(KERN_INFO "%s: cs89%c0%s rev %c found at %#8lx",
+ dev->name,
+ lp->chip_type==CS8900?'0':'2',
+ lp->chip_type==CS8920M?"M":"",
+ lp->chip_revision,
+ dev->base_addr);
+
+ /* Try to read the MAC address */
+ if ((readreg(dev, PP_SelfST) & (EEPROM_PRESENT | EEPROM_OK)) == 0) {
+ printk("\nmac89x0: No EEPROM, giving up now.\n");
+ return ENODEV;
+ } else {
+ for (i = 0; i < ETH_ALEN; i += 2) {
+ /* Big-endian (why??!) */
+ unsigned short s = readreg(dev, PP_IA + i);
+ dev->dev_addr[i] = s >> 8;
+ dev->dev_addr[i+1] = s & 0xff;
+ }
+ }
+
+ dev->irq = SLOT2IRQ(slot);
+ printk(" IRQ %d ADDR ", dev->irq);
+
+ /* print the ethernet address. */
+ for (i = 0; i < ETH_ALEN; i++)
+ printk("%2.2x%s", dev->dev_addr[i],
+ ((i < ETH_ALEN-1) ? ":" : ""));
+
+ dev->open = net_open;
+ dev->stop = net_close;
+ dev->hard_start_xmit = net_send_packet;
+ dev->get_stats = net_get_stats;
+ dev->set_multicast_list = &set_multicast_list;
+ dev->set_mac_address = &set_mac_address;
+
+ /* Fill in the fields of the net_device structure with ethernet values. */
+ ether_setup(dev);
+
+ printk("\n");
+ return 0;
+}
+
+/* This is useful for something, but I don't know what yet. */
+void __init reset_chip(struct net_device *dev)
+{
+ 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);
+
+ /* Wait until the chip is reset */
+ reset_start_time = jiffies;
+ while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2)
+ ;
+}
+
+/* Open/initialize the board. This is called (in the current kernel)
+ sometime after booting when the 'ifconfig' program is run.
+
+ This routine should set everything up anew at each open, even
+ registers that "should" only need to be set once at boot, so that
+ there is non-reboot way to recover if something goes wrong.
+ */
+static int
+net_open(struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ int i;
+
+ /* Disable the interrupt for now */
+ writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) & ~ENABLE_IRQ);
+
+ /* Grab the interrupt */
+ if (request_irq(dev->irq, &net_interrupt, 0, "cs89x0", dev))
+ return -EAGAIN;
+
+ /* Set up the IRQ - Apparently magic */
+ if (lp->chip_type == CS8900)
+ writereg(dev, PP_CS8900_ISAINT, 0);
+ else
+ writereg(dev, PP_CS8920_ISAINT, 0);
+
+ /* set the Ethernet address */
+ for (i=0; i < ETH_ALEN/2; i++)
+ writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
+
+ /* Turn on both receive and transmit operations */
+ writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
+
+ /* Receive only error free packets addressed to this card */
+ lp->rx_mode = 0;
+ writereg(dev, PP_RxCTL, DEF_RX_ACCEPT);
+
+ lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL;
+
+ writereg(dev, PP_RxCFG, lp->curr_rx_cfg);
+
+ writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL |
+ TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
+
+ writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL |
+ TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL);
+
+ /* now that we've got our act together, enable everything */
+ writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) | ENABLE_IRQ);
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int
+net_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ if (dev->tbusy) {
+ /* If we get here, some higher level has decided we are broken.
+ There should really be a "kick me" function call instead. */
+ int tickssofar = jiffies - dev->trans_start;
+ if (tickssofar < 5)
+ return 1;
+ if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
+ tx_done(dev) ? "IRQ conflict" : "network cable problem");
+ /* Try to restart the adaptor. */
+ dev->tbusy=0;
+ dev->trans_start = jiffies;
+ }
+
+ /* Block a timer-based transmit from overlapping. This could better be
+ done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
+ printk("%s: Transmitter access conflict.\n", dev->name);
+ else {
+ struct net_local *lp = (struct net_local *)dev->priv;
+ unsigned long flags;
+
+ if (net_debug > 3)
+ printk("%s: sent %d byte packet of type %x\n",
+ dev->name, skb->len,
+ (skb->data[ETH_ALEN+ETH_ALEN] << 8)
+ | skb->data[ETH_ALEN+ETH_ALEN+1]);
+
+ /* keep the upload from being interrupted, since we
+ ask the chip to start transmitting before the
+ whole packet has been completely uploaded. */
+ save_flags(flags);
+ cli();
+
+ /* initiate a transmit sequence */
+ writereg(dev, PP_TxCMD, lp->send_cmd);
+ writereg(dev, PP_TxLength, skb->len);
+
+ /* Test to see if the chip has allocated memory for the packet */
+ if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
+ /* Gasp! It hasn't. But that shouldn't happen since
+ we're waiting for TxOk, so return 1 and requeue this packet. */
+ restore_flags(flags);
+ return 1;
+ }
+
+ /* Write the contents of the packet */
+ memcpy_toio(dev->mem_start + PP_TxFrame, skb->data, skb->len+1);
+
+ restore_flags(flags);
+ dev->trans_start = jiffies;
+ }
+ dev_kfree_skb (skb);
+
+ return 0;
+}
+
+/* The typical workload of the driver:
+ Handle the network interface interrupts. */
+static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+ struct net_device *dev = dev_id;
+ struct net_local *lp;
+ int ioaddr, status;
+
+ if (dev == NULL) {
+ printk ("net_interrupt(): irq %d for unknown device.\n", irq);
+ return;
+ }
+ if (dev->interrupt)
+ printk("%s: Re-entering the interrupt handler.\n", dev->name);
+ dev->interrupt = 1;
+
+ ioaddr = dev->base_addr;
+ lp = (struct net_local *)dev->priv;
+
+ /* we MUST read all the events out of the ISQ, otherwise we'll never
+ get interrupted again. As a consequence, we can't have any limit
+ on the number of times we loop in the interrupt handler. The
+ hardware guarantees that eventually we'll run out of events. Of
+ 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 = swab16(readw(dev->base_addr + ISQ_PORT)))) {
+ if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);
+ switch(status & ISQ_EVENT_MASK) {
+ case ISQ_RECEIVER_EVENT:
+ /* Got a packet(s). */
+ net_rx(dev);
+ break;
+ case ISQ_TRANSMITTER_EVENT:
+ lp->stats.tx_packets++;
+ dev->tbusy = 0;
+ mark_bh(NET_BH); /* Inform upper layers. */
+ if ((status & TX_OK) == 0) lp->stats.tx_errors++;
+ if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++;
+ if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++;
+ if (status & TX_LATE_COL) lp->stats.tx_window_errors++;
+ if (status & TX_16_COL) lp->stats.tx_aborted_errors++;
+ break;
+ case ISQ_BUFFER_EVENT:
+ if (status & READY_FOR_TX) {
+ /* we tried to transmit a packet earlier,
+ but inexplicably ran out of buffers.
+ That shouldn't happen since we only ever
+ load one packet. Shrug. Do the right
+ thing anyway. */
+ dev->tbusy = 0;
+ mark_bh(NET_BH); /* Inform upper layers. */
+ }
+ if (status & TX_UNDERRUN) {
+ if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
+ lp->send_underrun++;
+ if (lp->send_underrun == 3) lp->send_cmd = TX_AFTER_381;
+ else if (lp->send_underrun == 6) lp->send_cmd = TX_AFTER_ALL;
+ }
+ break;
+ case ISQ_RX_MISS_EVENT:
+ lp->stats.rx_missed_errors += (status >>6);
+ break;
+ case ISQ_TX_COL_EVENT:
+ lp->stats.collisions += (status >>6);
+ break;
+ }
+ }
+ dev->interrupt = 0;
+ return;
+}
+
+/* We have a good packet(s), get it/them out of the buffers. */
+static void
+net_rx(struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ struct sk_buff *skb;
+ int status, length;
+
+ status = readreg(dev, PP_RxStatus);
+ if ((status & RX_OK) == 0) {
+ lp->stats.rx_errors++;
+ if (status & RX_RUNT) lp->stats.rx_length_errors++;
+ if (status & RX_EXTRA_DATA) lp->stats.rx_length_errors++;
+ if (status & RX_CRC_ERROR) if (!(status & (RX_EXTRA_DATA|RX_RUNT)))
+ /* per str 172 */
+ lp->stats.rx_crc_errors++;
+ if (status & RX_DRIBBLE) lp->stats.rx_frame_errors++;
+ return;
+ }
+
+ length = readreg(dev, PP_RxLength);
+ /* Malloc up new buffer. */
+ skb = alloc_skb(length, GFP_ATOMIC);
+ if (skb == NULL) {
+ printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+ lp->stats.rx_dropped++;
+ return;
+ }
+ skb->len = length;
+ skb->dev = dev;
+
+ memcpy_fromio(skb->data, dev->mem_start + PP_RxFrame, length);
+
+ if (net_debug > 3)printk("%s: received %d byte packet of type %x\n",
+ dev->name, length,
+ (skb->data[ETH_ALEN+ETH_ALEN] << 8)
+ | skb->data[ETH_ALEN+ETH_ALEN+1]);
+
+ skb->protocol=eth_type_trans(skb,dev);
+ netif_rx(skb);
+ lp->stats.rx_packets++;
+ lp->stats.rx_bytes+=skb->len;
+ return;
+}
+
+/* The inverse routine to net_open(). */
+static int
+net_close(struct net_device *dev)
+{
+
+ writereg(dev, PP_RxCFG, 0);
+ writereg(dev, PP_TxCFG, 0);
+ writereg(dev, PP_BufCFG, 0);
+ writereg(dev, PP_BusCTL, 0);
+
+ dev->start = 0;
+
+ free_irq(dev->irq, dev);
+
+ /* Update the statistics here. */
+
+ MOD_DEC_USE_COUNT;
+ return 0;
+
+}
+
+/* Get the current statistics. This may be called with the card open or
+ closed. */
+static struct net_device_stats *
+net_get_stats(struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+
+ cli();
+ /* Update the statistics from the device registers. */
+ lp->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
+ lp->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
+ sti();
+
+ return &lp->stats;
+}
+
+static void set_multicast_list(struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+
+ if(dev->flags&IFF_PROMISC)
+ {
+ lp->rx_mode = RX_ALL_ACCEPT;
+ }
+ else if((dev->flags&IFF_ALLMULTI)||dev->mc_list)
+ {
+ /* 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;
+
+ writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);
+
+ /* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */
+ writereg(dev, PP_RxCFG, lp->curr_rx_cfg |
+ (lp->rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0));
+}
+
+
+static int set_mac_address(struct net_device *dev, void *addr)
+{
+ int i;
+ if (dev->start)
+ return -EBUSY;
+ printk("%s: Setting MAC address to ", dev->name);
+ for (i = 0; i < 6; i++)
+ printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]);
+ printk(".\n");
+ /* set the Ethernet address */
+ for (i=0; i < ETH_ALEN/2; i++)
+ writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
+
+ return 0;
+}
+
+#ifdef MODULE
+
+static char namespace[16] = "";
+static struct net_device dev_cs89x0 = {
+ NULL,
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, 0, 0, NULL, NULL };
+
+static int debug=0;
+
+MODULE_PARM(debug, "i");
+
+EXPORT_NO_SYMBOLS;
+
+int
+init_module(void)
+{
+ struct net_local *lp;
+
+ net_debug = debug;
+ dev_cs89x0.name = namespace;
+ dev_cs89x0.init = mac89x0_probe;
+ dev_cs89x0.priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+ memset(dev_cs89x0.priv, 0, sizeof(struct net_local));
+ lp = (struct net_local *)dev_cs89x0.priv;
+
+ if (register_netdev(&dev_cs89x0) != 0) {
+ printk(KERN_WARNING "mac89x0.c: No card found\n");
+ return -ENXIO;
+ }
+ return 0;
+}
+
+void
+cleanup_module(void)
+{
+
+#endif
+#ifdef MODULE
+ writew(0, dev_cs89x0.base_addr + ADD_PORT);
+#endif
+#ifdef MODULE
+
+ if (dev_cs89x0.priv != NULL) {
+ /* Free up the private structure, or leak memory :-) */
+ unregister_netdev(&dev_cs89x0);
+ kfree(dev_cs89x0.priv);
+ dev_cs89x0.priv = NULL; /* gets re-allocated by cs89x0_probe1 */
+ }
+}
+#endif /* MODULE */
+
+/*
+ * Local variables:
+ * compile-command: "m68k-linux-gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -c -o mac89x0.o mac89x0.c"
+ * version-control: t
+ * kept-new-versions: 5
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ *
+ */
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
new file mode 100644
index 000000000..a7c347a7d
--- /dev/null
+++ b/drivers/net/macmace.c
@@ -0,0 +1,825 @@
+/*
+ * Driver for the Macintosh 68K onboard MACE controller with PSC
+ * driven DMA. The MACE driver code is derived from mace.c. The
+ * Mac68k theory of operation is courtesy of the MacBSD wizards.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ * Copyright (C) 1998 Alan Cox <alan@redhat.com>
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/macintosh.h>
+#include <asm/macints.h>
+#include <asm/mac_psc.h>
+#include "mace.h"
+
+#define N_RX_RING 8
+#define N_TX_RING 2
+#define MAX_TX_ACTIVE 1
+#define NCMDS_TX 1 /* dma commands per element in tx ring */
+#define RX_BUFLEN (ETH_FRAME_LEN + 8)
+#define TX_TIMEOUT HZ /* 1 second */
+
+/* Bits in transmit DMA status */
+#define TX_DMA_ERR 0x80
+
+/* The MACE is simply wired down on a Mac68K box */
+
+#define MACE_BASE (void *)(0x50F1C000)
+#define MACE_PROM (void *)(0x50F08001)
+
+struct mace68k_data
+{
+ volatile struct mace *mace;
+ volatile unsigned char *tx_ring;
+ volatile unsigned char *rx_ring;
+ int dma_intr;
+ unsigned char maccc;
+ struct net_device_stats stats;
+ struct timer_list tx_timeout;
+ int timeout_active;
+ int rx_slot, rx_done;
+ int tx_slot, tx_count;
+};
+
+struct mace_frame
+{
+ u16 len;
+ u16 status;
+ u16 rntpc;
+ u16 rcvcc;
+ u32 pad1;
+ u32 pad2;
+ u8 data[1];
+ /* And frame continues.. */
+};
+
+#define PRIV_BYTES sizeof(struct mace68k_data)
+
+extern void psc_debug_dump(void);
+
+static int mace68k_open(struct net_device *dev);
+static int mace68k_close(struct net_device *dev);
+static int mace68k_xmit_start(struct sk_buff *skb, struct net_device *dev);
+static struct net_device_stats *mace68k_stats(struct net_device *dev);
+static void mace68k_set_multicast(struct net_device *dev);
+static void mace68k_reset(struct net_device *dev);
+static int mace68k_set_address(struct net_device *dev, void *addr);
+static void mace68k_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void mace68k_dma_intr(int irq, void *dev_id, struct pt_regs *regs);
+static void mace68k_set_timeout(struct net_device *dev);
+static void mace68k_tx_timeout(unsigned long data);
+
+/*
+ * PSC DMA engine control. As you'd expect on a macintosh its
+ * more like a lawnmower engine supplied without instructions
+ *
+ * The basic theory of operation appears to be as follows.
+ *
+ * There are two sets of receive DMA registers and two sets
+ * of transmit DMA registers. Instead of the more traditional
+ * "ring buffer" approach the Mac68K DMA engine expects you
+ * to be loading one chain while the other runs, and then
+ * to flip register set. Each entry in the chain is a fixed
+ * length.
+ */
+
+/*
+ * Load a receive DMA channel with a base address and ring length
+ */
+
+static void psc_load_rxdma_base(int set, void *base)
+{
+ psc_write_word(PSC_ENETRD_CMD + set, 0x0100);
+ psc_write_long(PSC_ENETRD_ADDR + set, (u32)base);
+ psc_write_long(PSC_ENETRD_LEN + set, N_RX_RING);
+ psc_write_word(PSC_ENETRD_CMD + set, 0x9800);
+}
+
+/*
+ * Reset the receive DMA subsystem
+ */
+
+static void mace68k_rxdma_reset(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mace = mp->mace;
+ u8 mcc = mace->maccc;
+
+ /*
+ * Turn off receive
+ */
+
+ mcc&=~ENRCV;
+ mace->maccc=mcc;
+
+ /*
+ * Program the DMA
+ */
+
+ psc_write_word(PSC_ENETRD_CTL, 0x8800);
+ psc_load_rxdma_base(0x0, (void *)virt_to_bus(mp->rx_ring));
+ psc_write_word(PSC_ENETRD_CTL, 0x0400);
+
+ psc_write_word(PSC_ENETRD_CTL, 0x8800);
+ psc_load_rxdma_base(0x10, (void *)virt_to_bus(mp->rx_ring));
+ psc_write_word(PSC_ENETRD_CTL, 0x0400);
+
+ mace->maccc=mcc|ENRCV;
+
+#if 0
+ psc_write_word(PSC_ENETRD_CTL, 0x9800);
+ psc_write_word(PSC_ENETRD_CTL+0x10, 0x9800);
+#endif
+}
+
+/*
+ * Reset the transmit DMA subsystem
+ */
+
+static void mace68k_txdma_reset(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mace = mp->mace;
+ u8 mcc = mace->maccc;
+
+ psc_write_word(PSC_ENETWR_CTL,0x8800);
+
+ mace->maccc = mcc&~ENXMT;
+ psc_write_word(PSC_ENETWR_CTL,0x0400);
+ mace->maccc = mcc;
+}
+
+/*
+ * Disable DMA
+ */
+
+static void mace68k_dma_off(struct net_device *dev)
+{
+ psc_write_word(PSC_ENETRD_CTL, 0x8800);
+ psc_write_word(PSC_ENETRD_CTL, 0x1000);
+ psc_write_word(PSC_ENETRD_CMD, 0x1100);
+ psc_write_word(PSC_ENETRD_CMD+0x10, 0x1100);
+
+ psc_write_word(PSC_ENETWR_CTL, 0x8800);
+ psc_write_word(PSC_ENETWR_CTL, 0x1000);
+ psc_write_word(PSC_ENETWR_CMD, 0x1100);
+ psc_write_word(PSC_ENETWR_CMD+0x10, 0x1100);
+}
+
+/* Bit-reverse one byte of an ethernet hardware address. */
+
+static int bitrev(int b)
+{
+ int d = 0, i;
+
+ for (i = 0; i < 8; ++i, b >>= 1)
+ d = (d << 1) | (b & 1);
+ return d;
+}
+
+/*
+ * Not really much of a probe. The hardware table tells us if this
+ * model of Macintrash has a MACE (AV macintoshes)
+ */
+
+int mace68k_probe(struct net_device *unused)
+{
+ int j;
+ static int once=0;
+ struct mace68k_data *mp;
+ unsigned char *addr;
+ struct net_device *dev;
+ unsigned char checksum = 0;
+
+ /*
+ * There can be only one...
+ */
+
+ if (once) return -ENODEV;
+
+ once = 1;
+
+ if (macintosh_config->ether_type != MAC_ETHER_MACE) return -ENODEV;
+
+ printk("MACE ethernet should be present ");
+
+ dev = init_etherdev(0, PRIV_BYTES);
+ if(dev==NULL)
+ {
+ printk("no free memory.\n");
+ return -ENOMEM;
+ }
+ mp = (struct mace68k_data *) dev->priv;
+ dev->base_addr = (u32)MACE_BASE;
+ mp->mace = (volatile struct mace *) MACE_BASE;
+
+ printk("at 0x%p", mp->mace);
+
+ /*
+ * 16K RX ring and 4K TX ring should do nicely
+ */
+
+ mp->rx_ring=(void *)__get_free_pages(GFP_KERNEL, 2);
+ mp->tx_ring=(void *)__get_free_page(GFP_KERNEL);
+
+ printk(".");
+
+ if(mp->tx_ring==NULL || mp->rx_ring==NULL)
+ {
+ if(mp->tx_ring)
+ free_page((u32)mp->tx_ring);
+// if(mp->rx_ring)
+// __free_pages(mp->rx_ring,2);
+ printk("\nNo memory for ring buffers.\n");
+ return -ENOMEM;
+ }
+
+ /* We want the receive data to be uncached. We dont care about the
+ byte reading order */
+
+ printk(".");
+ kernel_set_cachemode((void *)mp->rx_ring, 16384, IOMAP_NOCACHE_NONSER);
+
+ printk(".");
+ /* The transmit buffer needs to be write through */
+ kernel_set_cachemode((void *)mp->tx_ring, 4096, IOMAP_WRITETHROUGH);
+
+ printk(" Ok\n");
+ dev->irq = IRQ_MAC_MACE;
+ printk(KERN_INFO "%s: MACE at", dev->name);
+
+ /*
+ * The PROM contains 8 bytes which total 0xFF when XOR'd
+ * together. Due to the usual peculiar apple brain damage
+ * the bytes are spaced out in a strange boundary and the
+ * bits are reversed.
+ */
+
+ addr = (void *)MACE_PROM;
+
+ for (j = 0; j < 6; ++j)
+ {
+ u8 v=bitrev(addr[j<<4]);
+ checksum^=v;
+ dev->dev_addr[j] = v;
+ printk("%c%.2x", (j ? ':' : ' '), dev->dev_addr[j]);
+ }
+ for (; j < 8; ++j)
+ {
+ checksum^=bitrev(addr[j<<4]);
+ }
+
+ if(checksum!=0xFF)
+ {
+ printk(" (invalid checksum)\n");
+ return -ENODEV;
+ }
+ printk("\n");
+
+ memset(&mp->stats, 0, sizeof(mp->stats));
+ init_timer(&mp->tx_timeout);
+ mp->timeout_active = 0;
+
+ dev->open = mace68k_open;
+ dev->stop = mace68k_close;
+ dev->hard_start_xmit = mace68k_xmit_start;
+ dev->get_stats = mace68k_stats;
+ dev->set_multicast_list = mace68k_set_multicast;
+ dev->set_mac_address = mace68k_set_address;
+
+ ether_setup(dev);
+
+ mp = (struct mace68k_data *) dev->priv;
+ mp->maccc = ENXMT | ENRCV;
+ mp->dma_intr = IRQ_MAC_MACE_DMA;
+
+ psc_write_word(PSC_ENETWR_CTL, 0x9000);
+ psc_write_word(PSC_ENETRD_CTL, 0x9000);
+ psc_write_word(PSC_ENETWR_CTL, 0x0400);
+ psc_write_word(PSC_ENETRD_CTL, 0x0400);
+
+ /* apple's driver doesn't seem to do this */
+ /* except at driver shutdown time... */
+#if 0
+ mace68k_dma_off(dev);
+#endif
+
+ return 0;
+}
+
+/*
+ * Reset a MACE controller
+ */
+
+static void mace68k_reset(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+ int i;
+
+ /* soft-reset the chip */
+ i = 200;
+ while (--i) {
+ mb->biucc = SWRST;
+ if (mb->biucc & SWRST) {
+ udelay(10);
+ continue;
+ }
+ break;
+ }
+ if (!i) {
+ printk(KERN_ERR "mace: cannot reset chip!\n");
+ return;
+ }
+
+ mb->biucc = XMTSP_64;
+ mb->imr = 0xff; /* disable all intrs for now */
+ i = mb->ir;
+ mb->maccc = 0; /* turn off tx, rx */
+ mb->utr = RTRD;
+ mb->fifocc = RCVFW_64;
+ mb->xmtfc = AUTO_PAD_XMIT; /* auto-pad short frames */
+
+ /* load up the hardware address */
+
+ mb->iac = ADDRCHG | PHYADDR;
+
+ while ((mb->iac & ADDRCHG) != 0);
+
+ for (i = 0; i < 6; ++i)
+ mb->padr = dev->dev_addr[i];
+
+ /* clear the multicast filter */
+ mb->iac = ADDRCHG | LOGADDR;
+
+ while ((mb->iac & ADDRCHG) != 0);
+
+ for (i = 0; i < 8; ++i)
+ mb->ladrf = 0;
+
+ mb->plscc = PORTSEL_GPSI + ENPLSIO;
+}
+
+/*
+ * Load the address on a mace controller.
+ */
+
+static int mace68k_set_address(struct net_device *dev, void *addr)
+{
+ unsigned char *p = addr;
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+ int i;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ /* load up the hardware address */
+ mb->iac = ADDRCHG | PHYADDR;
+ while ((mb->iac & ADDRCHG) != 0);
+
+ for (i = 0; i < 6; ++i)
+ mb->padr = dev->dev_addr[i] = p[i];
+ /* note: setting ADDRCHG clears ENRCV */
+ mb->maccc = mp->maccc;
+ restore_flags(flags);
+ return 0;
+}
+
+/*
+ * Open the Macintosh MACE. Most of this is playing with the DMA
+ * engine. The ethernet chip is quite friendly.
+ */
+
+static int mace68k_open(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+
+ /* reset the chip */
+ mace68k_reset(dev);
+
+ mp->rx_done = 0;
+ mace68k_rxdma_reset(dev);
+
+ /*
+ * The interrupt is fixed and comes off the PSC.
+ */
+
+ if (request_irq(dev->irq, mace68k_interrupt, 0, "68K MACE", dev))
+ {
+ printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq);
+ return -EAGAIN;
+ }
+
+ /*
+ * Ditto the DMA interrupt.
+ */
+
+ if (request_irq(IRQ_MAC_MACE_DMA, mace68k_dma_intr, 0, "68K MACE DMA",
+ dev))
+ {
+ printk(KERN_ERR "MACE: can't get irq %d\n", IRQ_MAC_MACE_DMA);
+ return -EAGAIN;
+ }
+
+ /* Activate the Mac DMA engine */
+
+ mp->tx_slot = 0; /* Using register set 0 */
+ mp->tx_count = 1; /* 1 Buffer ready for use */
+ mace68k_txdma_reset(dev);
+
+ /* turn it on! */
+ mb->maccc = mp->maccc;
+ /* enable all interrupts except receive interrupts */
+ mb->imr = RCVINT;
+ return 0;
+}
+
+/*
+ * Shut down the mace and its interrupt channel
+ */
+
+static int mace68k_close(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+
+ /* disable rx and tx */
+ mb->maccc = 0;
+ mb->imr = 0xff; /* disable all intrs */
+
+ /* disable rx and tx dma */
+
+ mace68k_dma_off(dev);
+
+ free_irq(dev->irq, dev);
+ free_irq(IRQ_MAC_MACE_DMA, dev);
+ return 0;
+}
+
+static inline void mace68k_set_timeout(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ if (mp->timeout_active)
+ del_timer(&mp->tx_timeout);
+ mp->tx_timeout.expires = jiffies + TX_TIMEOUT;
+ mp->tx_timeout.function = mace68k_tx_timeout;
+ mp->tx_timeout.data = (unsigned long) dev;
+ add_timer(&mp->tx_timeout);
+ mp->timeout_active = 1;
+ restore_flags(flags);
+}
+
+/*
+ * Transmit a frame
+ */
+
+static int mace68k_xmit_start(struct sk_buff *skb, struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ /*
+ * This may need atomic types ???
+ */
+
+ printk("mace68k_xmit_start: mp->tx_count = %d, dev->tbusy = %d, mp->tx_ring = %p (%p)\n",
+ mp->tx_count, dev->tbusy,
+ mp->tx_ring, virt_to_bus(mp->tx_ring));
+ psc_debug_dump();
+
+ if(mp->tx_count == 0)
+ {
+ dev->tbusy=1;
+ mace68k_dma_intr(IRQ_MAC_MACE_DMA, dev, NULL);
+ return 1;
+ }
+ mp->tx_count--;
+
+ /*
+ * FIXME:
+ * This is hackish. The memcpy probably isnt needed but
+ * the rules for alignment are not known. Ideally we'd like
+ * to just blast the skb directly to ethernet. We also don't
+ * use the ring properly - just a one frame buffer. That
+ * also requires cache pushes ;).
+ */
+ memcpy((void *)mp->tx_ring, skb, skb->len);
+ psc_write_long(PSC_ENETWR_ADDR + mp->tx_slot, virt_to_bus(mp->tx_ring));
+ psc_write_long(PSC_ENETWR_LEN + mp->tx_slot, skb->len);
+ psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x9800);
+ mp->stats.tx_packets++;
+ mp->stats.tx_bytes+=skb->len;
+ dev_kfree_skb(skb);
+ return 0;
+}
+
+static struct net_device_stats *mace68k_stats(struct net_device *dev)
+{
+ struct mace68k_data *p = (struct mace68k_data *) dev->priv;
+ return &p->stats;
+}
+
+/*
+ * CRC polynomial - used in working out multicast filter bits.
+ */
+#define CRC_POLY 0xedb88320
+
+static void mace68k_set_multicast(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+ int i, j, k, b;
+ unsigned long crc;
+
+ mp->maccc &= ~PROM;
+ if (dev->flags & IFF_PROMISC)
+ {
+ mp->maccc |= PROM;
+ } else
+ {
+ unsigned char multicast_filter[8];
+ struct dev_mc_list *dmi = dev->mc_list;
+
+ if (dev->flags & IFF_ALLMULTI)
+ {
+ for (i = 0; i < 8; i++)
+ multicast_filter[i] = 0xff;
+ } else
+ {
+ for (i = 0; i < 8; i++)
+ multicast_filter[i] = 0;
+ for (i = 0; i < dev->mc_count; i++)
+ {
+ crc = ~0;
+ for (j = 0; j < 6; ++j)
+ {
+ b = dmi->dmi_addr[j];
+ for (k = 0; k < 8; ++k)
+ {
+ if ((crc ^ b) & 1)
+ crc = (crc >> 1) ^ CRC_POLY;
+ else
+ crc >>= 1;
+ b >>= 1;
+ }
+ }
+ j = crc >> 26; /* bit number in multicast_filter */
+ multicast_filter[j >> 3] |= 1 << (j & 7);
+ dmi = dmi->next;
+ }
+ }
+#if 0
+ printk("Multicast filter :");
+ for (i = 0; i < 8; i++)
+ printk("%02x ", multicast_filter[i]);
+ printk("\n");
+#endif
+
+ mb->iac = ADDRCHG | LOGADDR;
+ while ((mb->iac & ADDRCHG) != 0);
+
+ for (i = 0; i < 8; ++i)
+ mb->ladrf = multicast_filter[i];
+ }
+ /* reset maccc */
+ mb->maccc = mp->maccc;
+}
+
+/*
+ * Miscellaneous interrupts are handled here. We may end up
+ * having to bash the chip on the head for bad errors
+ */
+
+static void mace68k_handle_misc_intrs(struct mace68k_data *mp, int intr)
+{
+ volatile struct mace *mb = mp->mace;
+ static int mace68k_babbles, mace68k_jabbers;
+
+ if (intr & MPCO)
+ mp->stats.rx_missed_errors += 256;
+ mp->stats.rx_missed_errors += mb->mpc; /* reading clears it */
+ if (intr & RNTPCO)
+ mp->stats.rx_length_errors += 256;
+ mp->stats.rx_length_errors += mb->rntpc; /* reading clears it */
+ if (intr & CERR)
+ ++mp->stats.tx_heartbeat_errors;
+ if (intr & BABBLE)
+ if (mace68k_babbles++ < 4)
+ printk(KERN_DEBUG "mace: babbling transmitter\n");
+ if (intr & JABBER)
+ if (mace68k_jabbers++ < 4)
+ printk(KERN_DEBUG "mace: jabbering transceiver\n");
+}
+
+/*
+ * A transmit error has occured. (We kick the transmit side from
+ * the DMA completion)
+ */
+
+static void mace68k_xmit_error(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+ u8 xmtfs, xmtrc;
+
+ xmtfs = mb->xmtfs;
+ xmtrc = mb->xmtrc;
+
+ if(xmtfs & XMTSV)
+ {
+ if(xmtfs & UFLO)
+ {
+ printk("%s: DMA underrun.\n", dev->name);
+ mp->stats.tx_errors++;
+ mp->stats.tx_fifo_errors++;
+ mace68k_reset(dev);
+ }
+ if(xmtfs & RTRY)
+ mp->stats.collisions++;
+ }
+ mark_bh(NET_BH);
+}
+
+/*
+ * A receive interrupt occured.
+ */
+
+static void mace68k_recv_interrupt(struct net_device *dev)
+{
+// struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+// volatile struct mace *mb = mp->mace;
+}
+
+/*
+ * Process the chip interrupt
+ */
+
+static void mace68k_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+ u8 ir;
+
+ ir = mb->ir;
+ mace68k_handle_misc_intrs(mp, ir);
+
+ if(ir&XMTINT)
+ mace68k_xmit_error(dev);
+ if(ir&RCVINT)
+ mace68k_recv_interrupt(dev);
+}
+
+static void mace68k_tx_timeout(unsigned long data)
+{
+// struct net_device *dev = (struct net_device *) data;
+// struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+// volatile struct mace *mb = mp->mace;
+}
+
+/*
+ * Handle a newly arrived frame
+ */
+
+static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ struct sk_buff *skb;
+
+ if(mf->status&RS_OFLO)
+ {
+ printk("%s: fifo overflow.\n", dev->name);
+ mp->stats.rx_errors++;
+ mp->stats.rx_fifo_errors++;
+ }
+ if(mf->status&(RS_CLSN|RS_FRAMERR|RS_FCSERR))
+ mp->stats.rx_errors++;
+
+ if(mf->status&RS_CLSN)
+ mp->stats.collisions++;
+ if(mf->status&RS_FRAMERR)
+ mp->stats.rx_frame_errors++;
+ if(mf->status&RS_FCSERR)
+ mp->stats.rx_crc_errors++;
+
+ skb = dev_alloc_skb(mf->len+2);
+ if(skb==NULL)
+ {
+ mp->stats.rx_dropped++;
+ return;
+ }
+ skb_reserve(skb,2);
+ memcpy(skb_put(skb, mf->len), mf->data, mf->len);
+
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ mp->stats.rx_packets++;
+ mp->stats.rx_bytes+=mf->len;
+}
+
+/*
+ * The PSC has passed us a DMA interrupt event.
+ */
+
+static void mace68k_dma_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+
+#if 0
+ u32 psc_status;
+
+ /* It seems this must be allowed to stabilise ?? */
+
+ while((psc_status=psc_read_long(0x0804))!=psc_read_long(0x0804));
+
+ /*
+ * Was this an ethernet event ?
+ */
+
+ if(psc_status&0x60000000)
+ {
+#endif
+ /*
+ * Process the read queue
+ */
+
+ u16 psc_status = psc_read_word(PSC_ENETRD_CTL);
+
+ printk("mace68k_dma_intr: PSC_ENETRD_CTL = %04X\n", (uint) psc_status);
+
+ if (psc_status & 0x2000) {
+ mace68k_rxdma_reset(dev);
+ mp->rx_done = 0;
+ } else if (psc_status & 0x100) {
+ int left;
+
+ psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x1100);
+ left=psc_read_long(PSC_ENETRD_LEN + mp->rx_slot);
+ /* read packets */
+
+ while(mp->rx_done < left)
+ {
+ struct mace_frame *mf=((struct mace_frame *)
+ mp->rx_ring)+mp->rx_done++;
+ mace_dma_rx_frame(dev, mf);
+ }
+
+ if(left == 0) /* Out of DMA room */
+ {
+ psc_load_rxdma_base(mp->rx_slot,
+ (void *)virt_to_phys(mp->rx_ring));
+ mp->rx_slot^=16;
+ mp->rx_done = 0;
+ }
+ else
+ {
+ psc_write_word(PSC_ENETRD_CMD+mp->rx_slot,
+ 0x9800);
+ }
+
+ }
+
+ /*
+ * Process the write queue
+ */
+
+ psc_status = psc_read_word(PSC_ENETWR_CTL);
+ printk("mace68k_dma_intr: PSC_ENETWR_CTL = %04X\n", (uint) psc_status);
+
+ /* apple's driver seems to loop over this until neither */
+ /* condition is true. - jmt */
+
+ if (psc_status & 0x2000) {
+ mace68k_txdma_reset(dev);
+ } else if (psc_status & 0x0100) {
+ psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x0100);
+ mp->tx_slot ^=16;
+ mp->tx_count++;
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+ }
+#if 0
+ }
+#endif
+}
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
index d14ccf3fb..dbb9129d7 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/macsonic.c
@@ -42,153 +42,245 @@
#include <asm/pgtable.h>
#include <asm/segment.h>
#include <asm/io.h>
+#include <asm/hwtest.h>
#include <asm/dma.h>
#include <asm/macintosh.h>
+#include <asm/macints.h>
+#include <asm/mac_via.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-
-#include <config/macsonic.h>
+#include <linux/module.h>
#define SREGS_PAD(n) u16 n;
#include "sonic.h"
-extern int mac_onboard_sonic_probe(void);
+static int sonic_debug = 0;
+static int sonic_version_printed = 0;
-static int setup_debug = -1;
-static int setup_offset = -1;
-static int setup_shift = -1;
+extern int macsonic_probe(struct net_device* dev);
+extern int mac_onboard_sonic_probe(struct net_device* dev);
+extern int mac_nubus_sonic_probe(struct net_device* dev);
-/*
- * This seems to be the right default for the Q800
- */
+/* For onboard SONIC */
+#define ONBOARD_SONIC_REGISTERS 0x50F0A000
+#define ONBOARD_SONIC_PROM_BASE 0x50f08000
-static int reg_offset = 0;
-static int reg_shift = 0;
+enum macsonic_type {
+ MACSONIC_DUODOCK,
+ MACSONIC_APPLE,
+ MACSONIC_APPLE16,
+ MACSONIC_DAYNA,
+ MACSONIC_DAYNALINK
+};
-/*
- * Macros to access SONIC registers
- */
-
-#define MAC_SONIC_REGISTERS 0x50F0A000
-#define MAC_SONIC_PROM_BASE 0x50f08000
-#define MAC_SONIC_IRQ 9 /* Nubus 9 */
+/* For the built-in SONIC in the Duo Dock */
+#define DUODOCK_SONIC_REGISTERS 0xe10000
+#define DUODOCK_SONIC_PROM_BASE 0xe12000
-/*
- * FIXME: We may need to invert the byte ordering. These should
- * be ok for other aspects as they are uncached spaces.
- * The original macros from jazzsonic.c works for me
- * on my LC 630, YMMV /Andreas Ehliar
- */
+/* For Apple-style NuBus SONIC */
+#define APPLE_SONIC_REGISTERS 0
+#define APPLE_SONIC_PROM_BASE 0x40000
-#if 0
-#define SONIC_READ(reg) \
- *((volatile unsigned int *)base_addr+((reg)<<2)+2)
+/* Daynalink LC SONIC */
+#define DAYNALINK_PROM_BASE 0x400000
-#define SONIC_WRITE(reg,val) \
- *((volatile unsigned int *)base_addr+((reg)<<2)+2) = val
-#else
-#define SONIC_READ(reg) \
- *((volatile unsigned int *)base_addr+reg)
+/* For Dayna-style NuBus SONIC (haven't seen one yet) */
+#define DAYNA_SONIC_REGISTERS 0x180000
+/* This is what OpenBSD says. However, this is definitely in NuBus
+ ROM space so we should be able to get it by walking the NuBus
+ resource directories */
+#define DAYNA_SONIC_MAC_ADDR 0xffe004
-#define SONIC_WRITE(reg,val) \
- *((volatile unsigned int *)base_addr+reg) = val
-#endif
+#define SONIC_READ_PROM(addr) readb(prom_addr+addr)
+
+int __init macsonic_probe(struct net_device* dev)
+{
+ int rv;
+
+ /* This will catch fatal stuff like -ENOMEM as well as success */
+ if ((rv = mac_onboard_sonic_probe(dev)) != -ENODEV)
+ return rv;
+ return mac_nubus_sonic_probe(dev);
+}
-#define SONIC_READ_PROM(addr) \
- *((volatile unsigned char *)prom_addr+addr)
/*
- * Function : mac_sonic_setup(char *str, int *ints)
- *
- * Purpose : booter command line initialization of the overrides array,
- *
- * Inputs : str - unused, ints - array of integer parameters with ints[0]
- * equal to the number of ints.
- *
- * Currently unused in the new driver; need to add settable parameters to the
- * detect function.
- *
+ * For reversing the PROM address
*/
-void mac_sonic_setup(char *str, int *ints) {
- /* Format of macsonic parameter is:
- * macsonic=<debug>,<offset>,<shift>
- * Negative values mean don't change.
- */
-
- /* Grmbl... the standard parameter parsing can't handle negative numbers
- * :-( So let's do it ourselves!
- */
+static unsigned char nibbletab[] = {0, 8, 4, 12, 2, 10, 6, 14,
+ 1, 9, 5, 13, 3, 11, 7, 15};
- int i = ints[0]+1, fact;
+static inline void bit_reverse_addr(unsigned char addr[6])
+{
+ int i;
- while( str && (isdigit(*str) || *str == '-') && i <= 10) {
- if (*str == '-')
- fact = -1, ++str;
- else
- fact = 1;
- ints[i++] = simple_strtoul( str, NULL, 0 ) * fact;
- if ((str = strchr( str, ',' )) != NULL)
- ++str;
- }
- ints[0] = i-1;
-
- if (ints[0] < 1) {
- printk( "mac_sonic_setup: no arguments!\n" );
- return;
- }
+ for(i = 0; i < 6; i++)
+ addr[i] = ((nibbletab[addr[i] & 0xf] << 4) |
+ nibbletab[(addr[i] >> 4) &0xf]);
+}
+
+int __init macsonic_init(struct net_device* dev)
+{
+ struct sonic_local* lp = (struct sonic_local *)dev->priv;
+ int i;
- if (ints[0] >= 1) {
- /* 0 <= n <= 2 */
- if (ints[1] >= 0 && ints[1] <= 8)
- setup_debug = ints[1];
- else if (ints[1] > 16)
- printk( "mac_sonic_setup: invalid debug level %d !\n", ints[1] );
+ /* Allocate the entire chunk of memory for the descriptors.
+ Note that this cannot cross a 64K boundary. */
+ for (i = 0; i < 20; i++) {
+ unsigned long desc_base, desc_top;
+ if ((lp->sonic_desc =
+ kmalloc(SIZEOF_SONIC_DESC
+ * SONIC_BUS_SCALE(lp->dma_bitmode), GFP_DMA)) == NULL) {
+ printk(KERN_ERR "%s: couldn't allocate descriptor buffers\n", dev->name);
+ }
+ desc_base = (unsigned long) lp->sonic_desc;
+ desc_top = desc_base + SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode);
+ if ((desc_top & 0xffff) >= (desc_base & 0xffff))
+ break;
+ /* Hmm. try again (FIXME: does this actually work?) */
+ kfree(lp->sonic_desc);
+ printk(KERN_DEBUG
+ "%s: didn't get continguous chunk [%08lx - %08lx], trying again\n",
+ dev->name, desc_base, desc_top);
}
- if (ints[0] >= 2) {
- /* 0 <= n <= 2 */
- if (ints[2] >= 0 && ints[2] <= 16)
- setup_offset = ints[2];
- else if (ints[2] > 16)
- printk( "mac_sonic_setup: invalid offset %d !\n", ints[2] );
+
+ if (lp->sonic_desc == NULL) {
+ printk(KERN_ERR "%s: tried 20 times to allocate descriptor buffers, giving up.\n",
+ dev->name);
+ return -ENOMEM;
+ }
+
+ /* Now set up the pointers to point to the appropriate places */
+ lp->cda = lp->sonic_desc;
+ lp->tda = lp->cda + (SIZEOF_SONIC_CDA * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+
+ /* FIXME, maybe we should use skbs */
+ if ((lp->rba = (char *)
+ kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_DMA)) == NULL) {
+ printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name);
+ return -ENOMEM;
}
- if (ints[0] >= 3) {
- /* 0 <= n <= 2 */
- if (ints[3] >= 0 && ints[3] <= 16)
- setup_shift = ints[3];
- else if (ints[3] > 16)
- printk( "mac_sonic_setup: invalid shift %d !\n", ints[3] );
+
+ {
+ int rs, ds;
+
+ /* almost always 12*4096, but let's not take chances */
+ rs = ((SONIC_NUM_RRS * SONIC_RBSIZE + 4095) / 4096) * 4096;
+ /* almost always under a page, but let's not take chances */
+ ds = ((SIZEOF_SONIC_DESC + 4095) / 4096) * 4096;
+ kernel_set_cachemode(lp->rba, rs, IOMAP_NOCACHE_SER);
+ kernel_set_cachemode(lp->sonic_desc, ds, IOMAP_NOCACHE_SER);
}
+
+#if 0
+ flush_cache_all();
+#endif
+
+ dev->open = sonic_open;
+ dev->stop = sonic_close;
+ dev->hard_start_xmit = sonic_send_packet;
+ dev->get_stats = sonic_get_stats;
+ dev->set_multicast_list = &sonic_multicast_list;
+
+ /*
+ * clear tally counter
+ */
+ sonic_write(dev, SONIC_CRCT, 0xffff);
+ sonic_write(dev, SONIC_FAET, 0xffff);
+ sonic_write(dev, SONIC_MPT, 0xffff);
+
+ /* Fill in the fields of the device structure with ethernet values. */
+ ether_setup(dev);
+ return 0;
}
-static int sonic_debug = 0;
+int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
+{
+ const int prom_addr = ONBOARD_SONIC_PROM_BASE;
+ int i;
-/*
- * For reversing the PROM address
- */
+ /* On NuBus boards we can sometimes look in the ROM resources.
+ No such luck for comm-slot/onboard. */
+ for(i = 0; i < 6; i++)
+ dev->dev_addr[i] = SONIC_READ_PROM(i);
-static unsigned char nibbletab[] = {0, 8, 4, 12, 2, 10, 6, 14,
- 1, 9, 5, 13, 3, 11, 7, 15};
+ /* Most of the time, the address is bit-reversed. The NetBSD
+ source has a rather long and detailed historical account of
+ why this is so. */
+ if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
+ memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+ memcmp(dev->dev_addr, "\x00\x05\x02", 3))
+ bit_reverse_addr(dev->dev_addr);
+ else
+ return 0;
+
+ /* If we still have what seems to be a bogus address, we'll
+ look in the CAM. The top entry should be ours. */
+ /* Danger! This only works if MacOS has already initialized
+ the card... */
+ if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
+ memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+ memcmp(dev->dev_addr, "\x00\x05\x02", 3))
+ {
+ unsigned short val;
+
+ printk(KERN_INFO "macsonic: PROM seems to be wrong, trying CAM entry 15\n");
+
+ sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
+ sonic_write(dev, SONIC_CEP, 15);
+
+ val = sonic_read(dev, SONIC_CAP2);
+ dev->dev_addr[5] = val >> 8;
+ dev->dev_addr[4] = val & 0xff;
+ val = sonic_read(dev, SONIC_CAP1);
+ dev->dev_addr[3] = val >> 8;
+ dev->dev_addr[2] = val & 0xff;
+ val = sonic_read(dev, SONIC_CAP0);
+ dev->dev_addr[1] = val >> 8;
+ dev->dev_addr[0] = val & 0xff;
+
+ printk(KERN_INFO "HW Address from CAM 15: ");
+ for (i = 0; i < 6; i++) {
+ printk("%2.2x", dev->dev_addr[i]);
+ if (i < 5)
+ printk(":");
+ }
+ printk("\n");
+ } else return 0;
-int __init mac_onboard_sonic_probe(void)
+ if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
+ memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+ memcmp(dev->dev_addr, "\x00\x05\x02", 3))
+ {
+ /*
+ * Still nonsense ... messed up someplace!
+ */
+ printk(KERN_ERR "macsonic: ERROR (INVALID MAC)\n");
+ return -EIO;
+ } else return 0;
+}
+
+int __init mac_onboard_sonic_probe(struct net_device* dev)
{
- struct net_device *dev;
- unsigned int silicon_revision;
- unsigned int val;
- struct sonic_local *lp;
+ /* Bwahahaha */
+ static int once_is_more_than_enough = 0;
+ struct sonic_local* lp;
int i;
- int base_addr = MAC_SONIC_REGISTERS;
- int prom_addr = MAC_SONIC_PROM_BASE;
- static int one=0;
- if (!MACH_IS_MAC)
+ if (once_is_more_than_enough)
return -ENODEV;
+ once_is_more_than_enough = 1;
- if(++one!=1) /* Only one is allowed */
+ if (!MACH_IS_MAC)
return -ENODEV;
printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. ");
@@ -198,288 +290,332 @@ int __init mac_onboard_sonic_probe(void)
printk("none.\n");
return -ENODEV;
}
-
- printk("yes\n");
-
- if (setup_debug >= 0)
- sonic_debug = setup_debug;
- /*
- * This may depend on the actual Mac model ... works for me.
- */
- reg_offset =
- (setup_offset >= 0) ? setup_offset : 0;
- reg_shift =
- (setup_shift >= 0) ? setup_shift : 0;
+ /* Bogus probing, on the models which may or may not have
+ Ethernet (BTW, the Ethernet *is* always at the same
+ address, and nothing else lives there, at least if Apple's
+ documentation is to be believed) */
+ if (macintosh_config->ident == MAC_MODEL_Q630 ||
+ macintosh_config->ident == MAC_MODEL_P588 ||
+ macintosh_config->ident == MAC_MODEL_C610) {
+ unsigned long flags;
+ int card_present;
+
+ save_flags(flags);
+ cli();
+ card_present = hwreg_present((void*)ONBOARD_SONIC_REGISTERS);
+ restore_flags(flags);
+
+ if (!card_present) {
+ printk("none.\n");
+ return -ENODEV;
+ }
+ }
- /*
- * get the Silicon Revision ID. If this is one of the known
- * one assume that we found a SONIC ethernet controller at
- * the expected location.
- * (This is not implemented in the Macintosh driver yet; need
- * to collect values from various sources. Mine is 0x4 ...)
- */
+ printk("yes\n");
- silicon_revision = SONIC_READ(SONIC_SR);
- if (sonic_debug > 1)
- printk("SONIC Silicon Revision = 0x%04x\n", silicon_revision);
+ if (dev) {
+ dev = init_etherdev(dev, sizeof(struct sonic_local));
+ /* methinks this will always be true but better safe than sorry */
+ if (dev->priv == NULL)
+ dev->priv = kmalloc(sizeof(struct sonic_local), GFP_KERNEL);
+ } else {
+ dev = init_etherdev(NULL, sizeof(struct sonic_local));
+ }
- /*
- * We need to allocate sonic_local later on, making sure it's
- * aligned on a 64k boundary. So, no space for dev->priv allocated
- * here ...
- */
- dev = init_etherdev(0,0);
-
- if(dev==NULL)
+ if (dev == NULL)
return -ENOMEM;
- printk("%s: %s found at 0x%08x, ",
- dev->name, "SONIC ethernet", base_addr);
+ lp = (struct sonic_local*) dev->priv;
+ memset(lp, 0, sizeof(struct sonic_local));
+ /* Danger! My arms are flailing wildly! You *must* set this
+ before using sonic_read() */
- if (sonic_debug > 1)
- printk("using offset %d shift %d,", reg_offset, reg_shift);
+ dev->base_addr = ONBOARD_SONIC_REGISTERS;
+ if (via_alt_mapping)
+ dev->irq = IRQ_AUTO_3;
+ else
+ dev->irq = IRQ_NUBUS_9;
- /* Fill in the 'dev' fields. */
- dev->base_addr = base_addr;
- dev->irq = MAC_SONIC_IRQ;
+ if (!sonic_version_printed) {
+ printk(KERN_INFO "%s", version);
+ sonic_version_printed = 1;
+ }
+ printk(KERN_INFO "%s: onboard / comm-slot SONIC at 0x%08lx\n",
+ dev->name, dev->base_addr);
+
+ /* Now do a song and dance routine in an attempt to determine
+ the bus width */
+
+ /* The PowerBook's SONIC is 16 bit always. */
+ if (macintosh_config->ident == MAC_MODEL_PB520) {
+ lp->reg_offset = 0;
+ lp->dma_bitmode = 0;
+ } else {
+ /* Some of the comm-slot cards are 16 bit. But some
+ of them are not. The 32-bit cards use offset 2 and
+ pad with zeroes or sometimes ones (I think...)
+ Therefore, if we try offset 0 and get a silicon
+ revision of 0, we assume 16 bit. */
+ int sr;
+
+ /* Technically this is not necessary since we zeroed
+ it above */
+ lp->reg_offset = 0;
+ lp->dma_bitmode = 0;
+ sr = sonic_read(dev, SONIC_SR);
+ if (sr == 0 || sr == 0xffff) {
+ lp->reg_offset = 2;
+ /* 83932 is 0x0004, 83934 is 0x0100 or 0x0101 */
+ sr = sonic_read(dev, SONIC_SR);
+ lp->dma_bitmode = 1;
+
+ }
+ printk(KERN_INFO
+ "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
+ dev->name, sr, lp->dma_bitmode?32:16, lp->reg_offset);
+ }
- /*
- * Put the sonic into software reset, then
- * retrieve and print the ethernet address.
- */
- SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+ /* Software reset, then initialize control registers. */
+ sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
+ sonic_write(dev, SONIC_DCR, SONIC_DCR_BMS |
+ SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS |
+ (lp->dma_bitmode ? SONIC_DCR_DW : 0));
+ /* This *must* be written back to in order to restore the
+ extended programmable output bits */
+ sonic_write(dev, SONIC_DCR2, 0);
- /*
- * We can't trust MacOS to initialise things it seems.
- */
+ /* Clear *and* disable interrupts to be on the safe side */
+ sonic_write(dev, SONIC_ISR,0x7fff);
+ sonic_write(dev, SONIC_IMR,0);
- if (sonic_debug > 1)
- printk("SONIC_DCR was %X\n",SONIC_READ(SONIC_DCR));
-
- SONIC_WRITE(SONIC_DCR,
- SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS | SONIC_DCR_DW);
+ /* Now look for the MAC address. */
+ if (mac_onboard_sonic_ethernet_addr(dev) != 0)
+ return -ENODEV;
- /*
- * We don't want floating spare IRQ's around, not on
- * level triggered systems!
- * Strange though - writing to the ISR only clears currently
- * pending IRQs, but doesn't disable them... Does this make
- * a difference?? Seems it does ...
- */
-#if 1
- SONIC_WRITE(SONIC_ISR,0x7fff);
- SONIC_WRITE(SONIC_IMR,0);
-#else
- SONIC_WRITE(SONIC_ISR, SONIC_IMR_DEFAULT);
-#endif
-
- /* This is how it is done in jazzsonic.c
- * It doesn't seem to work here though.
- */
- if (sonic_debug > 2) {
- printk("Retreiving CAM entry 0. This should be the HW address.\n");
-
- SONIC_WRITE(SONIC_CEP, 0);
- for (i = 0; i < 3; i++)
- {
- val = SONIC_READ(SONIC_CAP0 - i);
- dev->dev_addr[i * 2] = val;
- dev->dev_addr[i * 2 + 1] = val >> 8;
- }
+ printk(KERN_INFO "MAC ");
+ for (i = 0; i < 6; i++) {
+ printk("%2.2x", dev->dev_addr[i]);
+ if (i < 5)
+ printk(":");
+ }
- printk("HW Address from CAM 0: ");
- for (i = 0; i < 6; i++)
- {
- printk("%2.2x", dev->dev_addr[i]);
- if (i < 5)
- printk(":");
- }
- printk("\n");
+ printk(" IRQ %d\n", dev->irq);
- printk("Retreiving CAM entry 15. Another candidate...\n");
+ /* Shared init code */
+ return macsonic_init(dev);
+}
- /*
- * MacOS seems to use CAM entry 15 ...
- */
- SONIC_WRITE(SONIC_CEP, 15);
- for (i = 0; i < 3; i++)
- {
- val = SONIC_READ(SONIC_CAP0 - i);
- dev->dev_addr[i * 2] = val;
- dev->dev_addr[i * 2 + 1] = val >> 8;
- }
+int __init mac_nubus_sonic_ethernet_addr(struct net_device* dev,
+ unsigned long prom_addr,
+ int id)
+{
+ int i;
+ for(i = 0; i < 6; i++)
+ dev->dev_addr[i] = SONIC_READ_PROM(i);
+ /* For now we are going to assume that they're all bit-reversed */
+ bit_reverse_addr(dev->dev_addr);
- printk("HW Address from CAM 15: ");
- for (i = 0; i < 6; i++)
- {
- printk("%2.2x", dev->dev_addr[i]);
- if (i < 5)
- printk(":");
- }
- printk("\n");
- }
+ return 0;
+}
- /*
- * if we can read the PROM, we're safe :-)
- */
- if (sonic_debug > 1)
- printk("Retreiving HW address from the PROM: ");
-
- for(i=0;i<6;i++){
- dev->dev_addr[i]=SONIC_READ_PROM(i);
- }
- if (sonic_debug > 1) {
- for (i = 0; i < 6; i++)
- {
- printk("%2.2x", dev->dev_addr[i]);
- if (i < 5)
- printk(":");
- }
- printk("\n");
+int __init macsonic_ident(struct nubus_dev* ndev)
+{
+ if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC &&
+ ndev->dr_sw == NUBUS_DRSW_SONIC_LC)
+ return MACSONIC_DAYNALINK;
+ if (ndev->dr_hw == NUBUS_DRHW_SONIC &&
+ ndev->dr_sw == NUBUS_DRSW_APPLE) {
+ /* There has to be a better way to do this... */
+ if (strstr(ndev->board->name, "DuoDock"))
+ return MACSONIC_DUODOCK;
+ else
+ return MACSONIC_APPLE;
}
- /*
- * If its not one of these we have
- * screwed up on this Mac model
- */
+ return -1;
+}
- if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
- memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
- memcmp(dev->dev_addr, "\x00\x05\x02", 3))
+int __init mac_nubus_sonic_probe(struct net_device* dev)
+{
+ static int slots = 0;
+ struct nubus_dev* ndev = NULL;
+ struct sonic_local* lp;
+ unsigned long base_addr, prom_addr;
+ u16 sonic_dcr;
+ int id;
+ int i;
+ int reg_offset, dma_bitmode;
+
+ /* Find the first SONIC that hasn't been initialized already */
+ while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
+ NUBUS_TYPE_ETHERNET, ndev)) != NULL)
{
- /*
- * Try bit reversed
- */
- for(i=0;i<6;i++){
- val = SONIC_READ_PROM(i);
- dev->dev_addr[i]=(nibbletab[val & 0xf] << 4) |
- nibbletab[(val >> 4) &0xf];
- }
- if (sonic_debug > 1) {
- printk("Trying bit reversed: ");
- for (i = 0; i < 6; i++)
- {
- printk("%2.2x", dev->dev_addr[i]);
- if (i < 5)
- printk(":");
- }
- printk("\n");
- }
- if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
- memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
- memcmp(dev->dev_addr, "\x00\x05\x02", 3))
- {
- /*
- * Still nonsense ... messed up someplace!
- */
- printk("ERROR (INVALID MAC)\n");
- return -EIO;
- }
+ /* Have we seen it already? */
+ if (slots & (1<<ndev->board->slot))
+ continue;
+ slots |= 1<<ndev->board->slot;
+
+ /* Is it one of ours? */
+ if ((id = macsonic_ident(ndev)) != -1)
+ break;
}
- printk(" MAC ");
- for (i = 0; i < 6; i++)
- {
+ if (ndev == NULL)
+ return -ENODEV;
+
+ switch (id) {
+ case MACSONIC_DUODOCK:
+ base_addr = ndev->board->slot_addr + DUODOCK_SONIC_REGISTERS;
+ prom_addr = ndev->board->slot_addr + DUODOCK_SONIC_PROM_BASE;
+ sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT0 | SONIC_DCR_RFT1
+ | SONIC_DCR_TFT0;
+ reg_offset = 2;
+ dma_bitmode = 1;
+ break;
+ case MACSONIC_APPLE:
+ base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
+ prom_addr = ndev->board->slot_addr + APPLE_SONIC_PROM_BASE;
+ sonic_dcr = SONIC_DCR_BMS | SONIC_DCR_RFT1 | SONIC_DCR_TFT0;
+ reg_offset = 0;
+ dma_bitmode = 1;
+ break;
+ case MACSONIC_APPLE16:
+ base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
+ prom_addr = ndev->board->slot_addr + APPLE_SONIC_PROM_BASE;
+ sonic_dcr = SONIC_DCR_EXBUS
+ | SONIC_DCR_RFT1 | SONIC_DCR_TFT0
+ | SONIC_DCR_PO1 | SONIC_DCR_BMS;
+ reg_offset = 0;
+ dma_bitmode = 0;
+ break;
+ case MACSONIC_DAYNALINK:
+ base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
+ prom_addr = ndev->board->slot_addr + DAYNALINK_PROM_BASE;
+ sonic_dcr = SONIC_DCR_RFT1 | SONIC_DCR_TFT0
+ | SONIC_DCR_PO1 | SONIC_DCR_BMS;
+ reg_offset = 0;
+ dma_bitmode = 0;
+ break;
+ case MACSONIC_DAYNA:
+ base_addr = ndev->board->slot_addr + DAYNA_SONIC_REGISTERS;
+ prom_addr = ndev->board->slot_addr + DAYNA_SONIC_MAC_ADDR;
+ sonic_dcr = SONIC_DCR_BMS
+ | SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_PO1;
+ reg_offset = 0;
+ dma_bitmode = 0;
+ break;
+ default:
+ printk(KERN_ERR "macsonic: WTF, id is %d\n", id);
+ return -ENODEV;
+ }
+
+ if (dev) {
+ dev = init_etherdev(dev, sizeof(struct sonic_local));
+ /* methinks this will always be true but better safe than sorry */
+ if (dev->priv == NULL)
+ dev->priv = kmalloc(sizeof(struct sonic_local), GFP_KERNEL);
+ } else {
+ dev = init_etherdev(NULL, sizeof(struct sonic_local));
+ }
+
+ if (dev == NULL)
+ return -ENOMEM;
+
+ lp = (struct sonic_local*) dev->priv;
+ memset(lp, 0, sizeof(struct sonic_local));
+ /* Danger! My arms are flailing wildly! You *must* set this
+ before using sonic_read() */
+ lp->reg_offset = reg_offset;
+ lp->dma_bitmode = dma_bitmode;
+ dev->base_addr = base_addr;
+ dev->irq = SLOT2IRQ(ndev->board->slot);
+
+ if (!sonic_version_printed) {
+ printk(KERN_INFO "%s", version);
+ sonic_version_printed = 1;
+ }
+ printk(KERN_INFO "%s: %s in slot %X\n",
+ dev->name, ndev->board->name, ndev->board->slot);
+ printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
+ dev->name, sonic_read(dev, SONIC_SR), dma_bitmode?32:16, reg_offset);
+
+ /* Software reset, then initialize control registers. */
+ sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
+ sonic_write(dev, SONIC_DCR, sonic_dcr
+ | (dma_bitmode ? SONIC_DCR_DW : 0));
+
+ /* Clear *and* disable interrupts to be on the safe side */
+ sonic_write(dev, SONIC_ISR,0x7fff);
+ sonic_write(dev, SONIC_IMR,0);
+
+ /* Now look for the MAC address. */
+ if (mac_nubus_sonic_ethernet_addr(dev, prom_addr, id) != 0)
+ return -ENODEV;
+
+ printk(KERN_INFO "MAC ");
+ for (i = 0; i < 6; i++) {
printk("%2.2x", dev->dev_addr[i]);
if (i < 5)
printk(":");
}
+ printk(" IRQ %d\n", dev->irq);
- printk(" IRQ %d\n", MAC_SONIC_IRQ);
-
- /* Initialize the device structure. */
- if (dev->priv == NULL)
- {
- if (sonic_debug > 2) {
- printk("Allocating memory for dev->priv aka lp\n");
- printk("Memory to allocate: %d\n",sizeof(*lp));
- }
- /*
- * the memory be located in the same 64kb segment
- */
- lp = NULL;
- i = 0;
- do
- {
- lp = (struct sonic_local *) kmalloc(sizeof(*lp), GFP_KERNEL);
- if ((unsigned long) lp >> 16 != ((unsigned long) lp + sizeof(*lp)) >> 16)
- {
- /* FIXME, free the memory later */
- kfree(lp);
- lp = NULL;
- }
- }
- while (lp == NULL && i++ < 20);
+ /* Shared init code */
+ return macsonic_init(dev);
+}
- if (lp == NULL)
- {
- printk("%s: couldn't allocate memory for descriptors\n",
- dev->name);
- return -ENOMEM;
- }
+#ifdef MODULE
+static char namespace[16] = "";
+static struct net_device dev_macsonic = {
+ NULL,
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, 0, 0, NULL, NULL };
- if (sonic_debug > 2) {
- printk("Memory allocated after %d tries\n",i);
- }
+MODULE_PARM(sonic_debug, "i");
- /* XXX sonic_local has the TDA, RRA, RDA, don't cache */
- kernel_set_cachemode((u32)lp, 8192, IOMAP_NOCACHE_SER);
- memset(lp, 0, sizeof(struct sonic_local));
+EXPORT_NO_SYMBOLS;
- lp->cda_laddr = (u32)lp;
- if (sonic_debug > 2) {
- printk("memory allocated for sonic at 0x%x\n",lp);
- }
- lp->tda_laddr = lp->cda_laddr + sizeof(lp->cda);
- lp->rra_laddr = lp->tda_laddr + sizeof(lp->tda);
- lp->rda_laddr = lp->rra_laddr + sizeof(lp->rra);
-
- /* allocate receive buffer area */
- /* FIXME, maybe we should use skbs */
- if ((lp->rba = (char *) kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL)
- {
- printk("%s: couldn't allocate receive buffers\n", dev->name);
- return -ENOMEM;
- }
- /* XXX RBA written by Sonic, not cached either */
- kernel_set_cachemode((u32)lp->rba, 6*8192, IOMAP_NOCACHE_SER);
- lp->rba_laddr = (u32)lp->rba;
- flush_cache_all();
- dev->priv = (struct sonic_local *) lp;
- }
- lp = (struct sonic_local *) dev->priv;
- dev->open = sonic_open;
- dev->stop = sonic_close;
- dev->hard_start_xmit = sonic_send_packet;
- dev->get_stats = sonic_get_stats;
- dev->set_multicast_list = &sonic_multicast_list;
+int
+init_module(void)
+{
+ dev_macsonic.name = namespace;
+ dev_macsonic.init = macsonic_probe;
- /* Fill in the fields of the device structure with ethernet values. */
- ether_setup(dev);
+ if (register_netdev(&dev_macsonic) != 0) {
+ printk(KERN_WARNING "macsonic.c: No card found\n");
+ return -ENXIO;
+ }
return 0;
}
-/*
- * SONIC uses a nubus IRQ
- */
+void
+cleanup_module(void)
+{
+ if (dev_macsonic.priv != NULL) {
+ unregister_netdev(&dev_macsonic);
+ kfree(dev_macsonic.priv);
+ dev_macsonic.priv = NULL;
+ }
+}
+#endif /* MODULE */
-#define sonic_request_irq(irq, vec, flags, name, dev) \
- nubus_request_irq(irq, dev, vec)
-#define sonic_free_irq(irq,id) nubus_free_irq(irq)
-/*
- * No funnies on memory mapping.
- */
+#define vdma_alloc(foo, bar) ((u32)foo)
+#define vdma_free(baz)
+#define sonic_chiptomem(bat) (bat)
+#define PHYSADDR(quux) (quux)
-#define sonic_chiptomem(x) (x)
+#include "sonic.c"
/*
- * No VDMA on a Macintosh. So we need request no such facility.
+ * Local variables:
+ * compile-command: "m68k-linux-gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -c -o macsonic.o macsonic.c"
+ * version-control: t
+ * kept-new-versions: 5
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ *
*/
-
-#define vdma_alloc(x,y) ((u32)(x))
-#define vdma_free(x)
-#define PHYSADDR(x) (x)
-
-#include "sonic.c"
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 4fff08b7f..006e36f4b 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -21,7 +21,7 @@
*/
-static char *version = "sun3lance.c: v1.0 12/12/96 Sam Creasey (sammy@users.qual.net)\n";
+static char *version = "sun3lance.c: v1.1 11/17/1999 Sam Creasey (sammy@oh.verio.com)\n";
#include <linux/module.h>
@@ -263,6 +263,8 @@ static int __init lance_probe( struct net_device *dev)
int i;
static int did_version = 0;
int found = 0;
+ volatile unsigned short *ioaddr_probe;
+ unsigned short tmp1, tmp2;
/* LANCE_OBIO can be found within the IO pmeg with some effort */
for(ioaddr = 0xfe00000; ioaddr < (0xfe00000 +
@@ -282,6 +284,23 @@ static int __init lance_probe( struct net_device *dev)
if(!found)
return 0;
+ /* test to see if there's really a lance here */
+ /* (CSRO_INIT shouldn't be readable) */
+
+ ioaddr_probe = (volatile unsigned short *)ioaddr;
+ tmp1 = ioaddr_probe[0];
+ tmp2 = ioaddr_probe[1];
+
+ ioaddr_probe[1] = CSR0;
+ ioaddr_probe[0] = CSR0_INIT | CSR0_STOP;
+
+ if(ioaddr_probe[0] != CSR0_STOP) {
+ ioaddr_probe[0] = tmp1;
+ ioaddr_probe[1] = tmp2;
+
+ return 0;
+ }
+
init_etherdev( dev, sizeof(struct lance_private) );
if (!dev->priv)
dev->priv = kmalloc( sizeof(struct lance_private), GFP_KERNEL );
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 10e466a5d..b86c8fdb6 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -1,4 +1,4 @@
-/* $Id: sunbmac.c,v 1.12 1999/12/15 14:07:58 davem Exp $
+/* $Id: sunbmac.c,v 1.13 2000/01/28 13:42:29 jj Exp $
* sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters.
*
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index eb76a9fee..65d8315d9 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -1,4 +1,4 @@
-/* $Id: sunhme.c,v 1.84 1999/12/15 14:08:03 davem Exp $
+/* $Id: sunhme.c,v 1.85 2000/01/28 13:42:27 jj Exp $
* sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching,
* auto carrier detecting ethernet driver. Also known as the
* "Happy Meal Ethernet" found on SunSwift SBUS cards.
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 3c499ba38..45b671ae7 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -1,4 +1,4 @@
-/* $Id: sunlance.c,v 1.92 1999/12/15 14:08:09 davem Exp $
+/* $Id: sunlance.c,v 1.93 2000/01/28 13:42:31 jj Exp $
* lance.c: Linux/Sparc/Lance driver
*
* Written 1995, 1996 by Miguel de Icaza
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index 2a170a0a6..53e0c756f 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -1,4 +1,4 @@
-/* $Id: sunqe.c,v 1.40 1999/12/15 14:08:13 davem Exp $
+/* $Id: sunqe.c,v 1.41 2000/01/28 13:42:30 jj Exp $
* sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver.
* Once again I am out to prove that every ethernet
* controller out there can be most efficiently programmed