Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/drivers/net/wan/lmc/Makefile b/drivers/net/wan/lmc/Makefile
new file mode 100644
index 0000000..dabdcfe
--- /dev/null
+++ b/drivers/net/wan/lmc/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for the Lan Media 21140 based WAN cards
+# Specifically the 1000,1200,5200,5245
+#
+
+obj-$(CONFIG_LANMEDIA) += lmc.o
+
+lmc-objs := lmc_debug.o lmc_media.o lmc_main.o lmc_proto.o
+
+# Like above except every packet gets echoed to KERN_DEBUG
+# in hex
+#
+# DBDEF = \
+# -DDEBUG \
+# -DLMC_PACKET_LOG
+
+EXTRA_CFLAGS += -I. $(DBGDEF)
diff --git a/drivers/net/wan/lmc/lmc.h b/drivers/net/wan/lmc/lmc.h
new file mode 100644
index 0000000..882e58c
--- /dev/null
+++ b/drivers/net/wan/lmc/lmc.h
@@ -0,0 +1,33 @@
+#ifndef _LMC_H_
+#define _LMC_H_
+
+#include "lmc_var.h"
+
+/*
+ * prototypes for everyone
+ */
+int lmc_probe(struct net_device * dev);
+unsigned lmc_mii_readreg(lmc_softc_t * const sc, unsigned
+      			  devaddr, unsigned regno);
+void lmc_mii_writereg(lmc_softc_t * const sc, unsigned devaddr,
+			       unsigned regno, unsigned data);
+void lmc_led_on(lmc_softc_t * const, u_int32_t);
+void lmc_led_off(lmc_softc_t * const, u_int32_t);
+unsigned lmc_mii_readreg(lmc_softc_t * const, unsigned, unsigned);
+void lmc_mii_writereg(lmc_softc_t * const, unsigned, unsigned, unsigned);
+void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits);
+void lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits);
+
+int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+
+extern lmc_media_t lmc_ds3_media;
+extern lmc_media_t lmc_ssi_media;
+extern lmc_media_t lmc_t1_media;
+extern lmc_media_t lmc_hssi_media;
+
+#ifdef _DBG_EVENTLOG
+static void lmcEventLog( u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3 );
+#endif
+
+#endif
+
diff --git a/drivers/net/wan/lmc/lmc_debug.c b/drivers/net/wan/lmc/lmc_debug.c
new file mode 100644
index 0000000..9dccd95
--- /dev/null
+++ b/drivers/net/wan/lmc/lmc_debug.c
@@ -0,0 +1,85 @@
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/interrupt.h>
+
+#include "lmc_debug.h"
+
+/*
+ * Prints out len, max to 80 octets using printk, 20 per line
+ */
+void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
+{
+#ifdef DEBUG
+#ifdef LMC_PACKET_LOG
+  int iNewLine = 1;
+  char str[80], *pstr;
+  
+  sprintf(str, KERN_DEBUG "lmc: %s: ", type);
+  pstr = str+strlen(str);
+  
+  if(iLen > 240){
+      printk(KERN_DEBUG "lmc: Printing 240 chars... out of: %d\n", iLen);
+    iLen = 240;
+  }
+  else{
+      printk(KERN_DEBUG "lmc: Printing %d chars\n", iLen);
+  }
+
+  while(iLen > 0) 
+    {
+      sprintf(pstr, "%02x ", *ucData);
+      pstr+=3;
+      ucData++;
+      if( !(iNewLine % 20))
+	{
+	  sprintf(pstr, "\n");
+	  printk(str);
+	  sprintf(str, KERN_DEBUG "lmc: %s: ", type);
+	  pstr=str+strlen(str);
+	}
+      iNewLine++;
+      iLen--;
+    }
+  sprintf(pstr, "\n");
+  printk(str);
+#endif
+#endif
+}
+
+#ifdef DEBUG
+u_int32_t lmcEventLogIndex = 0;
+u_int32_t lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS];
+#endif
+
+void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3)
+{
+#ifdef DEBUG
+  lmcEventLogBuf[lmcEventLogIndex++] = EventNum;
+  lmcEventLogBuf[lmcEventLogIndex++] = arg2;
+  lmcEventLogBuf[lmcEventLogIndex++] = arg3;
+  lmcEventLogBuf[lmcEventLogIndex++] = jiffies;
+
+  lmcEventLogIndex &= (LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS) - 1;
+#endif
+}
+
+void lmc_trace(struct net_device *dev, char *msg){
+#ifdef LMC_TRACE
+    unsigned long j = jiffies + 3; /* Wait for 50 ms */
+
+    if(in_interrupt()){
+        printk("%s: * %s\n", dev->name, msg);
+//        while(time_before(jiffies, j+10))
+//            ;
+    }
+    else {
+        printk("%s: %s\n", dev->name, msg);
+        while(time_before(jiffies, j))
+            schedule();
+    }
+#endif
+}
+
+
+/* --------------------------- end if_lmc_linux.c ------------------------ */
diff --git a/drivers/net/wan/lmc/lmc_debug.h b/drivers/net/wan/lmc/lmc_debug.h
new file mode 100644
index 0000000..cf35638
--- /dev/null
+++ b/drivers/net/wan/lmc/lmc_debug.h
@@ -0,0 +1,52 @@
+#ifndef _LMC_DEBUG_H_
+#define _LMC_DEBUG_H_
+
+#ifdef DEBUG
+#ifdef LMC_PACKET_LOG
+#define LMC_CONSOLE_LOG(x,y,z) lmcConsoleLog((x), (y), (z))
+#else
+#define LMC_CONSOLE_LOG(x,y,z)
+#endif
+#else
+#define LMC_CONSOLE_LOG(x,y,z)
+#endif
+
+
+
+/* Debug --- Event log definitions --- */
+/* EVENTLOGSIZE*EVENTLOGARGS needs to be a power of 2 */
+#define LMC_EVENTLOGSIZE 1024	/* number of events in eventlog */
+#define LMC_EVENTLOGARGS 4		/* number of args for each event */
+
+/* event indicators */
+#define LMC_EVENT_XMT           1
+#define LMC_EVENT_XMTEND        2
+#define LMC_EVENT_XMTINT        3
+#define LMC_EVENT_RCVINT        4
+#define LMC_EVENT_RCVEND        5
+#define LMC_EVENT_INT           6
+#define LMC_EVENT_XMTINTTMO     7
+#define LMC_EVENT_XMTPRCTMO     8
+#define LMC_EVENT_INTEND        9
+#define LMC_EVENT_RESET1       10
+#define LMC_EVENT_RESET2       11
+#define LMC_EVENT_FORCEDRESET  12
+#define LMC_EVENT_WATCHDOG     13
+#define LMC_EVENT_BADPKTSURGE  14
+#define LMC_EVENT_TBUSY0       15
+#define LMC_EVENT_TBUSY1       16
+
+
+#ifdef DEBUG
+extern u_int32_t lmcEventLogIndex;
+extern u_int32_t lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS];
+#define LMC_EVENT_LOG(x, y, z) lmcEventLog((x), (y), (z))
+#else
+#define LMC_EVENT_LOG(x,y,z)
+#endif /* end ifdef _DBG_EVENTLOG */
+
+void lmcConsoleLog(char *type, unsigned char *ucData, int iLen);
+void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3);
+void lmc_trace(struct net_device *dev, char *msg);
+
+#endif
diff --git a/drivers/net/wan/lmc/lmc_ioctl.h b/drivers/net/wan/lmc/lmc_ioctl.h
new file mode 100644
index 0000000..57dd861
--- /dev/null
+++ b/drivers/net/wan/lmc/lmc_ioctl.h
@@ -0,0 +1,257 @@
+#ifndef _LMC_IOCTL_H_
+#define _LMC_IOCTL_H_
+/*	$Id: lmc_ioctl.h,v 1.15 2000/04/06 12:16:43 asj Exp $	*/
+
+ /*
+  * Copyright (c) 1997-2000 LAN Media Corporation (LMC)
+  * All rights reserved.  www.lanmedia.com
+  *
+  * This code is written by:
+  * Andrew Stanley-Jones (asj@cban.com)
+  * Rob Braun (bbraun@vix.com),
+  * Michael Graff (explorer@vix.com) and
+  * Matt Thomas (matt@3am-software.com).
+  *
+  * This software may be used and distributed according to the terms
+  * of the GNU General Public License version 2, incorporated herein by reference.
+  */
+
+#define LMCIOCGINFO             SIOCDEVPRIVATE+3 /* get current state */
+#define LMCIOCSINFO             SIOCDEVPRIVATE+4 /* set state to user values */
+#define LMCIOCGETLMCSTATS       SIOCDEVPRIVATE+5
+#define LMCIOCCLEARLMCSTATS     SIOCDEVPRIVATE+6
+#define LMCIOCDUMPEVENTLOG      SIOCDEVPRIVATE+7
+#define LMCIOCGETXINFO          SIOCDEVPRIVATE+8
+#define LMCIOCSETCIRCUIT        SIOCDEVPRIVATE+9
+#define LMCIOCUNUSEDATM         SIOCDEVPRIVATE+10
+#define LMCIOCRESET             SIOCDEVPRIVATE+11
+#define LMCIOCT1CONTROL         SIOCDEVPRIVATE+12
+#define LMCIOCIFTYPE            SIOCDEVPRIVATE+13
+#define LMCIOCXILINX            SIOCDEVPRIVATE+14
+
+#define LMC_CARDTYPE_UNKNOWN            -1
+#define LMC_CARDTYPE_HSSI               1       /* probed card is a HSSI card */
+#define LMC_CARDTYPE_DS3                2       /* probed card is a DS3 card */
+#define LMC_CARDTYPE_SSI                3       /* probed card is a SSI card */
+#define LMC_CARDTYPE_T1                 4       /* probed card is a T1 card */
+
+#define LMC_CTL_CARDTYPE_LMC5200	0	/* HSSI */
+#define LMC_CTL_CARDTYPE_LMC5245	1	/* DS3 */
+#define LMC_CTL_CARDTYPE_LMC1000	2	/* SSI, V.35 */
+#define LMC_CTL_CARDTYPE_LMC1200        3       /* DS1 */
+
+#define LMC_CTL_OFF			0	/* generic OFF value */
+#define LMC_CTL_ON			1	/* generic ON value */
+
+#define LMC_CTL_CLOCK_SOURCE_EXT	0	/* clock off line */
+#define LMC_CTL_CLOCK_SOURCE_INT	1	/* internal clock */
+
+#define LMC_CTL_CRC_LENGTH_16		16
+#define LMC_CTL_CRC_LENGTH_32		32
+#define LMC_CTL_CRC_BYTESIZE_2          2
+#define LMC_CTL_CRC_BYTESIZE_4          4
+
+
+#define LMC_CTL_CABLE_LENGTH_LT_100FT	0	/* DS3 cable < 100 feet */
+#define LMC_CTL_CABLE_LENGTH_GT_100FT	1	/* DS3 cable >= 100 feet */
+
+#define LMC_CTL_CIRCUIT_TYPE_E1 0
+#define LMC_CTL_CIRCUIT_TYPE_T1 1
+
+/*
+ * IFTYPE defines
+ */
+#define LMC_PPP         1               /* use sppp interface */
+#define LMC_NET         2               /* use direct net interface */
+#define LMC_RAW         3               /* use direct net interface */
+
+/*
+ * These are not in the least IOCTL related, but I want them common.
+ */
+/*
+ * assignments for the GPIO register on the DEC chip (common)
+ */
+#define LMC_GEP_INIT		0x01 /* 0: */
+#define LMC_GEP_RESET		0x02 /* 1: */
+#define LMC_GEP_MODE		0x10 /* 4: */
+#define LMC_GEP_DP		0x20 /* 5: */
+#define LMC_GEP_DATA		0x40 /* 6: serial out */
+#define LMC_GEP_CLK	        0x80 /* 7: serial clock */
+
+/*
+ * HSSI GPIO assignments
+ */
+#define LMC_GEP_HSSI_ST		0x04 /* 2: receive timing sense (deprecated) */
+#define LMC_GEP_HSSI_CLOCK	0x08 /* 3: clock source */
+
+/*
+ * T1 GPIO assignments
+ */
+#define LMC_GEP_SSI_GENERATOR	0x04 /* 2: enable prog freq gen serial i/f */
+#define LMC_GEP_SSI_TXCLOCK	0x08 /* 3: provide clock on TXCLOCK output */
+
+/*
+ * Common MII16 bits
+ */
+#define LMC_MII16_LED0         0x0080
+#define LMC_MII16_LED1         0x0100
+#define LMC_MII16_LED2         0x0200
+#define LMC_MII16_LED3         0x0400  /* Error, and the red one */
+#define LMC_MII16_LED_ALL      0x0780  /* LED bit mask */
+#define LMC_MII16_FIFO_RESET   0x0800
+
+/*
+ * definitions for HSSI
+ */
+#define LMC_MII16_HSSI_TA      0x0001
+#define LMC_MII16_HSSI_CA      0x0002
+#define LMC_MII16_HSSI_LA      0x0004
+#define LMC_MII16_HSSI_LB      0x0008
+#define LMC_MII16_HSSI_LC      0x0010
+#define LMC_MII16_HSSI_TM      0x0020
+#define LMC_MII16_HSSI_CRC     0x0040
+
+/*
+ * assignments for the MII register 16 (DS3)
+ */
+#define LMC_MII16_DS3_ZERO	0x0001
+#define LMC_MII16_DS3_TRLBK	0x0002
+#define LMC_MII16_DS3_LNLBK	0x0004
+#define LMC_MII16_DS3_RAIS	0x0008
+#define LMC_MII16_DS3_TAIS	0x0010
+#define LMC_MII16_DS3_BIST	0x0020
+#define LMC_MII16_DS3_DLOS	0x0040
+#define LMC_MII16_DS3_CRC	0x1000
+#define LMC_MII16_DS3_SCRAM	0x2000
+#define LMC_MII16_DS3_SCRAM_LARS 0x4000
+
+/* Note: 2 pairs of LEDs where swapped by mistake
+ * in Xilinx code for DS3 & DS1 adapters */
+#define LMC_DS3_LED0    0x0100          /* bit 08  yellow */
+#define LMC_DS3_LED1    0x0080          /* bit 07  blue   */
+#define LMC_DS3_LED2    0x0400          /* bit 10  green  */
+#define LMC_DS3_LED3    0x0200          /* bit 09  red    */
+
+/*
+ * framer register 0 and 7 (7 is latched and reset on read)
+ */
+#define LMC_FRAMER_REG0_DLOS            0x80    /* digital loss of service */
+#define LMC_FRAMER_REG0_OOFS            0x40    /* out of frame sync */
+#define LMC_FRAMER_REG0_AIS             0x20    /* alarm indication signal */
+#define LMC_FRAMER_REG0_CIS             0x10    /* channel idle */
+#define LMC_FRAMER_REG0_LOC             0x08    /* loss of clock */
+
+/*
+ * Framer register 9 contains the blue alarm signal
+ */
+#define LMC_FRAMER_REG9_RBLUE          0x02     /* Blue alarm failure */
+
+/*
+ * Framer register 0x10 contains xbit error
+ */
+#define LMC_FRAMER_REG10_XBIT          0x01     /* X bit error alarm failure */
+
+/*
+ * And SSI, LMC1000
+ */
+#define LMC_MII16_SSI_DTR	0x0001	/* DTR output RW */
+#define LMC_MII16_SSI_DSR	0x0002	/* DSR input RO */
+#define LMC_MII16_SSI_RTS	0x0004	/* RTS output RW */
+#define LMC_MII16_SSI_CTS	0x0008	/* CTS input RO */
+#define LMC_MII16_SSI_DCD	0x0010	/* DCD input RO */
+#define LMC_MII16_SSI_RI		0x0020	/* RI input RO */
+#define LMC_MII16_SSI_CRC                0x1000  /* CRC select - RW */
+
+/*
+ * bits 0x0080 through 0x0800 are generic, and described
+ * above with LMC_MII16_LED[0123] _LED_ALL, and _FIFO_RESET
+ */
+#define LMC_MII16_SSI_LL		0x1000	/* LL output RW */
+#define LMC_MII16_SSI_RL		0x2000	/* RL output RW */
+#define LMC_MII16_SSI_TM		0x4000	/* TM input RO */
+#define LMC_MII16_SSI_LOOP	0x8000	/* loopback enable RW */
+
+/*
+ * Some of the MII16 bits are mirrored in the MII17 register as well,
+ * but let's keep thing separate for now, and get only the cable from
+ * the MII17.
+ */
+#define LMC_MII17_SSI_CABLE_MASK	0x0038	/* mask to extract the cable type */
+#define LMC_MII17_SSI_CABLE_SHIFT 3	/* shift to extract the cable type */
+
+/*
+ * And T1, LMC1200
+ */
+#define LMC_MII16_T1_UNUSED1    0x0003
+#define LMC_MII16_T1_XOE                0x0004
+#define LMC_MII16_T1_RST                0x0008  /* T1 chip reset - RW */
+#define LMC_MII16_T1_Z                  0x0010  /* output impedance T1=1, E1=0 output - RW */
+#define LMC_MII16_T1_INTR               0x0020  /* interrupt from 8370 - RO */
+#define LMC_MII16_T1_ONESEC             0x0040  /* one second square wave - ro */
+
+#define LMC_MII16_T1_LED0               0x0100
+#define LMC_MII16_T1_LED1               0x0080
+#define LMC_MII16_T1_LED2               0x0400
+#define LMC_MII16_T1_LED3               0x0200
+#define LMC_MII16_T1_FIFO_RESET 0x0800
+
+#define LMC_MII16_T1_CRC                0x1000  /* CRC select - RW */
+#define LMC_MII16_T1_UNUSED2    0xe000
+
+
+/* 8370 framer registers  */
+
+#define T1FRAMER_ALARM1_STATUS  0x47
+#define T1FRAMER_ALARM2_STATUS  0x48
+#define T1FRAMER_FERR_LSB               0x50
+#define T1FRAMER_FERR_MSB               0x51    /* framing bit error counter */
+#define T1FRAMER_LCV_LSB                0x54
+#define T1FRAMER_LCV_MSB                0x55    /* line code violation counter */
+#define T1FRAMER_AERR                   0x5A
+
+/* mask for the above AERR register */
+#define T1FRAMER_LOF_MASK               (0x0f0) /* receive loss of frame */
+#define T1FRAMER_COFA_MASK              (0x0c0) /* change of frame alignment */
+#define T1FRAMER_SEF_MASK               (0x03)  /* severely errored frame  */
+
+/* 8370 framer register ALM1 (0x47) values
+ * used to determine link status
+ */
+
+#define T1F_SIGFRZ      0x01    /* signaling freeze */
+#define T1F_RLOF        0x02    /* receive loss of frame alignment */
+#define T1F_RLOS        0x04    /* receive loss of signal */
+#define T1F_RALOS       0x08    /* receive analog loss of signal or RCKI loss of clock */
+#define T1F_RAIS        0x10    /* receive alarm indication signal */
+#define T1F_UNUSED      0x20
+#define T1F_RYEL        0x40    /* receive yellow alarm */
+#define T1F_RMYEL       0x80    /* receive multiframe yellow alarm */
+
+#define LMC_T1F_WRITE       0
+#define LMC_T1F_READ        1
+
+typedef struct lmc_st1f_control {
+  int command;
+  int address;
+  int value;
+  char __user *data;
+} lmc_t1f_control;
+
+enum lmc_xilinx_c {
+    lmc_xilinx_reset = 1,
+    lmc_xilinx_load_prom = 2,
+    lmc_xilinx_load = 3
+};
+
+struct lmc_xilinx_control {
+    enum lmc_xilinx_c command;
+    int len;
+    char __user *data;
+};
+
+/* ------------------ end T1 defs ------------------- */
+
+#define LMC_MII_LedMask                 0x0780
+#define LMC_MII_LedBitPos               7
+
+#endif
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
new file mode 100644
index 0000000..15e545f
--- /dev/null
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -0,0 +1,2201 @@
+ /*
+  * Copyright (c) 1997-2000 LAN Media Corporation (LMC)
+  * All rights reserved.  www.lanmedia.com
+  *
+  * This code is written by:
+  * Andrew Stanley-Jones (asj@cban.com)
+  * Rob Braun (bbraun@vix.com),
+  * Michael Graff (explorer@vix.com) and
+  * Matt Thomas (matt@3am-software.com).
+  *
+  * With Help By:
+  * David Boggs
+  * Ron Crane
+  * Alan Cox
+  *
+  * This software may be used and distributed according to the terms
+  * of the GNU General Public License version 2, incorporated herein by reference.
+  *
+  * Driver for the LanMedia LMC5200, LMC5245, LMC1000, LMC1200 cards.
+  *
+  * To control link specific options lmcctl is required.
+  * It can be obtained from ftp.lanmedia.com.
+  *
+  * Linux driver notes:
+  * Linux uses the device struct lmc_private to pass private information
+  * arround.
+  *
+  * The initialization portion of this driver (the lmc_reset() and the
+  * lmc_dec_reset() functions, as well as the led controls and the
+  * lmc_initcsrs() functions.
+  *
+  * The watchdog function runs every second and checks to see if
+  * we still have link, and that the timing source is what we expected
+  * it to be.  If link is lost, the interface is marked down, and
+  * we no longer can transmit.
+  *
+  */
+
+/* $Id: lmc_main.c,v 1.36 2000/04/11 05:25:25 asj Exp $ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/in.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/inet.h>
+#include <linux/bitops.h>
+
+#include <net/syncppp.h>
+
+#include <asm/processor.h>             /* Processor type for cache alignment. */
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+//#include <asm/spinlock.h>
+
+#define DRIVER_MAJOR_VERSION     1
+#define DRIVER_MINOR_VERSION    34
+#define DRIVER_SUB_VERSION       0
+
+#define DRIVER_VERSION  ((DRIVER_MAJOR_VERSION << 8) + DRIVER_MINOR_VERSION)
+
+#include "lmc.h"
+#include "lmc_var.h"
+#include "lmc_ioctl.h"
+#include "lmc_debug.h"
+#include "lmc_proto.h"
+
+static int lmc_first_load = 0;
+
+static int LMC_PKT_BUF_SZ = 1542;
+
+static struct pci_device_id lmc_pci_tbl[] = {
+	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,
+	  PCI_VENDOR_ID_LMC, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,
+	  PCI_ANY_ID, PCI_VENDOR_ID_LMC },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, lmc_pci_tbl);
+MODULE_LICENSE("GPL");
+
+
+static int lmc_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int lmc_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int lmc_rx (struct net_device *dev);
+static int lmc_open(struct net_device *dev);
+static int lmc_close(struct net_device *dev);
+static struct net_device_stats *lmc_get_stats(struct net_device *dev);
+static irqreturn_t lmc_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, size_t csr_size);
+static void lmc_softreset(lmc_softc_t * const);
+static void lmc_running_reset(struct net_device *dev);
+static int lmc_ifdown(struct net_device * const);
+static void lmc_watchdog(unsigned long data);
+static void lmc_reset(lmc_softc_t * const sc);
+static void lmc_dec_reset(lmc_softc_t * const sc);
+static void lmc_driver_timeout(struct net_device *dev);
+
+/*
+ * linux reserves 16 device specific IOCTLs.  We call them
+ * LMCIOC* to control various bits of our world.
+ */
+int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
+{
+    lmc_softc_t *sc;
+    lmc_ctl_t ctl;
+    int ret;
+    u_int16_t regVal;
+    unsigned long flags;
+
+    struct sppp *sp;
+
+    ret = -EOPNOTSUPP;
+
+    sc = dev->priv;
+
+    lmc_trace(dev, "lmc_ioctl in");
+
+    /*
+     * Most functions mess with the structure
+     * Disable interrupts while we do the polling
+     */
+    spin_lock_irqsave(&sc->lmc_lock, flags);
+
+    switch (cmd) {
+        /*
+         * Return current driver state.  Since we keep this up
+         * To date internally, just copy this out to the user.
+         */
+    case LMCIOCGINFO: /*fold01*/
+        if (copy_to_user(ifr->ifr_data, &sc->ictl, sizeof (lmc_ctl_t)))
+            return -EFAULT;
+        ret = 0;
+        break;
+
+    case LMCIOCSINFO: /*fold01*/
+        sp = &((struct ppp_device *) dev)->sppp;
+        if (!capable(CAP_NET_ADMIN)) {
+            ret = -EPERM;
+            break;
+        }
+
+        if(dev->flags & IFF_UP){
+            ret = -EBUSY;
+            break;
+        }
+
+        if (copy_from_user(&ctl, ifr->ifr_data, sizeof (lmc_ctl_t)))
+            return -EFAULT;
+
+        sc->lmc_media->set_status (sc, &ctl);
+
+        if(ctl.crc_length != sc->ictl.crc_length) {
+            sc->lmc_media->set_crc_length(sc, ctl.crc_length);
+	    if (sc->ictl.crc_length == LMC_CTL_CRC_LENGTH_16)
+		sc->TxDescriptControlInit |=  LMC_TDES_ADD_CRC_DISABLE;
+	    else
+		sc->TxDescriptControlInit &= ~LMC_TDES_ADD_CRC_DISABLE;
+        }
+
+        if (ctl.keepalive_onoff == LMC_CTL_OFF)
+            sp->pp_flags &= ~PP_KEEPALIVE;	/* Turn off */
+        else
+            sp->pp_flags |= PP_KEEPALIVE;	/* Turn on */
+
+        ret = 0;
+        break;
+
+    case LMCIOCIFTYPE: /*fold01*/
+        {
+            u_int16_t	old_type = sc->if_type;
+            u_int16_t	new_type;
+
+	    if (!capable(CAP_NET_ADMIN)) {
+		ret = -EPERM;
+		break;
+	    }
+
+	    if (copy_from_user(&new_type, ifr->ifr_data, sizeof(u_int16_t)))
+                return -EFAULT;
+
+            
+	    if (new_type == old_type)
+	    {
+		ret = 0 ;
+		break;				/* no change */
+            }
+            
+            lmc_proto_close(sc);
+            lmc_proto_detach(sc);
+
+            sc->if_type = new_type;
+//            lmc_proto_init(sc);
+            lmc_proto_attach(sc);
+            lmc_proto_open(sc);
+
+	    ret = 0 ;
+	    break ;
+	}
+
+    case LMCIOCGETXINFO: /*fold01*/
+        sc->lmc_xinfo.Magic0 = 0xBEEFCAFE;
+
+        sc->lmc_xinfo.PciCardType = sc->lmc_cardtype;
+        sc->lmc_xinfo.PciSlotNumber = 0;
+        sc->lmc_xinfo.DriverMajorVersion = DRIVER_MAJOR_VERSION;
+        sc->lmc_xinfo.DriverMinorVersion = DRIVER_MINOR_VERSION;
+        sc->lmc_xinfo.DriverSubVersion = DRIVER_SUB_VERSION;
+        sc->lmc_xinfo.XilinxRevisionNumber =
+            lmc_mii_readreg (sc, 0, 3) & 0xf;
+        sc->lmc_xinfo.MaxFrameSize = LMC_PKT_BUF_SZ;
+        sc->lmc_xinfo.link_status = sc->lmc_media->get_link_status (sc);
+        sc->lmc_xinfo.mii_reg16 = lmc_mii_readreg (sc, 0, 16);
+
+        sc->lmc_xinfo.Magic1 = 0xDEADBEEF;
+
+        if (copy_to_user(ifr->ifr_data, &sc->lmc_xinfo,
+                         sizeof (struct lmc_xinfo)))
+            return -EFAULT;
+        ret = 0;
+
+        break;
+
+    case LMCIOCGETLMCSTATS: /*fold01*/
+        if (sc->lmc_cardtype == LMC_CARDTYPE_T1){
+            lmc_mii_writereg (sc, 0, 17, T1FRAMER_FERR_LSB);
+            sc->stats.framingBitErrorCount +=
+                lmc_mii_readreg (sc, 0, 18) & 0xff;
+            lmc_mii_writereg (sc, 0, 17, T1FRAMER_FERR_MSB);
+            sc->stats.framingBitErrorCount +=
+                (lmc_mii_readreg (sc, 0, 18) & 0xff) << 8;
+            lmc_mii_writereg (sc, 0, 17, T1FRAMER_LCV_LSB);
+            sc->stats.lineCodeViolationCount +=
+                lmc_mii_readreg (sc, 0, 18) & 0xff;
+            lmc_mii_writereg (sc, 0, 17, T1FRAMER_LCV_MSB);
+            sc->stats.lineCodeViolationCount +=
+                (lmc_mii_readreg (sc, 0, 18) & 0xff) << 8;
+            lmc_mii_writereg (sc, 0, 17, T1FRAMER_AERR);
+            regVal = lmc_mii_readreg (sc, 0, 18) & 0xff;
+
+            sc->stats.lossOfFrameCount +=
+                (regVal & T1FRAMER_LOF_MASK) >> 4;
+            sc->stats.changeOfFrameAlignmentCount +=
+                (regVal & T1FRAMER_COFA_MASK) >> 2;
+            sc->stats.severelyErroredFrameCount +=
+                regVal & T1FRAMER_SEF_MASK;
+        }
+
+        if (copy_to_user(ifr->ifr_data, &sc->stats,
+                         sizeof (struct lmc_statistics)))
+            return -EFAULT;
+
+        ret = 0;
+        break;
+
+    case LMCIOCCLEARLMCSTATS: /*fold01*/
+        if (!capable(CAP_NET_ADMIN)){
+            ret = -EPERM;
+            break;
+        }
+
+        memset (&sc->stats, 0, sizeof (struct lmc_statistics));
+        sc->stats.check = STATCHECK;
+        sc->stats.version_size = (DRIVER_VERSION << 16) +
+            sizeof (struct lmc_statistics);
+        sc->stats.lmc_cardtype = sc->lmc_cardtype;
+        ret = 0;
+        break;
+
+    case LMCIOCSETCIRCUIT: /*fold01*/
+        if (!capable(CAP_NET_ADMIN)){
+            ret = -EPERM;
+            break;
+        }
+
+        if(dev->flags & IFF_UP){
+            ret = -EBUSY;
+            break;
+        }
+
+        if (copy_from_user(&ctl, ifr->ifr_data, sizeof (lmc_ctl_t)))
+            return -EFAULT;
+        sc->lmc_media->set_circuit_type(sc, ctl.circuit_type);
+        sc->ictl.circuit_type = ctl.circuit_type;
+        ret = 0;
+
+        break;
+
+    case LMCIOCRESET: /*fold01*/
+        if (!capable(CAP_NET_ADMIN)){
+            ret = -EPERM;
+            break;
+        }
+
+        /* Reset driver and bring back to current state */
+        printk (" REG16 before reset +%04x\n", lmc_mii_readreg (sc, 0, 16));
+        lmc_running_reset (dev);
+        printk (" REG16 after reset +%04x\n", lmc_mii_readreg (sc, 0, 16));
+
+        LMC_EVENT_LOG(LMC_EVENT_FORCEDRESET, LMC_CSR_READ (sc, csr_status), lmc_mii_readreg (sc, 0, 16));
+
+        ret = 0;
+        break;
+
+#ifdef DEBUG
+    case LMCIOCDUMPEVENTLOG:
+        if (copy_to_user(ifr->ifr_data, &lmcEventLogIndex, sizeof (u32)))
+            return -EFAULT;
+        if (copy_to_user(ifr->ifr_data + sizeof (u32), lmcEventLogBuf, sizeof (lmcEventLogBuf)))
+            return -EFAULT;
+
+        ret = 0;
+        break;
+#endif /* end ifdef _DBG_EVENTLOG */
+    case LMCIOCT1CONTROL: /*fold01*/
+        if (sc->lmc_cardtype != LMC_CARDTYPE_T1){
+            ret = -EOPNOTSUPP;
+            break;
+        }
+        break;
+    case LMCIOCXILINX: /*fold01*/
+        {
+            struct lmc_xilinx_control xc; /*fold02*/
+
+            if (!capable(CAP_NET_ADMIN)){
+                ret = -EPERM;
+                break;
+            }
+
+            /*
+             * Stop the xwitter whlie we restart the hardware
+             */
+            netif_stop_queue(dev);
+
+            if (copy_from_user(&xc, ifr->ifr_data, sizeof (struct lmc_xilinx_control)))
+                return -EFAULT;
+            switch(xc.command){
+            case lmc_xilinx_reset: /*fold02*/
+                {
+                    u16 mii;
+                    mii = lmc_mii_readreg (sc, 0, 16);
+
+                    /*
+                     * Make all of them 0 and make input
+                     */
+                    lmc_gpio_mkinput(sc, 0xff);
+
+                    /*
+                     * make the reset output
+                     */
+                    lmc_gpio_mkoutput(sc, LMC_GEP_RESET);
+
+                    /*
+                     * RESET low to force configuration.  This also forces
+                     * the transmitter clock to be internal, but we expect to reset
+                     * that later anyway.
+                     */
+
+                    sc->lmc_gpio &= ~LMC_GEP_RESET;
+                    LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
+
+
+                    /*
+                     * hold for more than 10 microseconds
+                     */
+                    udelay(50);
+
+                    sc->lmc_gpio |= LMC_GEP_RESET;
+                    LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
+
+
+                    /*
+                     * stop driving Xilinx-related signals
+                     */
+                    lmc_gpio_mkinput(sc, 0xff);
+
+                    /* Reset the frammer hardware */
+                    sc->lmc_media->set_link_status (sc, 1);
+                    sc->lmc_media->set_status (sc, NULL);
+//                    lmc_softreset(sc);
+
+                    {
+                        int i;
+                        for(i = 0; i < 5; i++){
+                            lmc_led_on(sc, LMC_DS3_LED0);
+                            mdelay(100);
+                            lmc_led_off(sc, LMC_DS3_LED0);
+                            lmc_led_on(sc, LMC_DS3_LED1);
+                            mdelay(100);
+                            lmc_led_off(sc, LMC_DS3_LED1);
+                            lmc_led_on(sc, LMC_DS3_LED3);
+                            mdelay(100);
+                            lmc_led_off(sc, LMC_DS3_LED3);
+                            lmc_led_on(sc, LMC_DS3_LED2);
+                            mdelay(100);
+                            lmc_led_off(sc, LMC_DS3_LED2);
+                        }
+                    }
+                    
+                    
+
+                    ret = 0x0;
+
+                }
+
+                break;
+            case lmc_xilinx_load_prom: /*fold02*/
+                {
+                    u16 mii;
+                    int timeout = 500000;
+                    mii = lmc_mii_readreg (sc, 0, 16);
+
+                    /*
+                     * Make all of them 0 and make input
+                     */
+                    lmc_gpio_mkinput(sc, 0xff);
+
+                    /*
+                     * make the reset output
+                     */
+                    lmc_gpio_mkoutput(sc,  LMC_GEP_DP | LMC_GEP_RESET);
+
+                    /*
+                     * RESET low to force configuration.  This also forces
+                     * the transmitter clock to be internal, but we expect to reset
+                     * that later anyway.
+                     */
+
+                    sc->lmc_gpio &= ~(LMC_GEP_RESET | LMC_GEP_DP);
+                    LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
+
+
+                    /*
+                     * hold for more than 10 microseconds
+                     */
+                    udelay(50);
+
+                    sc->lmc_gpio |= LMC_GEP_DP | LMC_GEP_RESET;
+                    LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
+
+                    /*
+                     * busy wait for the chip to reset
+                     */
+                    while( (LMC_CSR_READ(sc, csr_gp) & LMC_GEP_INIT) == 0 &&
+                           (timeout-- > 0))
+                        ;
+
+
+                    /*
+                     * stop driving Xilinx-related signals
+                     */
+                    lmc_gpio_mkinput(sc, 0xff);
+
+                    ret = 0x0;
+                    
+
+                    break;
+
+                }
+
+            case lmc_xilinx_load: /*fold02*/
+                {
+                    char *data;
+                    int pos;
+                    int timeout = 500000;
+
+                    if(xc.data == 0x0){
+                            ret = -EINVAL;
+                            break;
+                    }
+
+                    data = kmalloc(xc.len, GFP_KERNEL);
+                    if(data == 0x0){
+                            printk(KERN_WARNING "%s: Failed to allocate memory for copy\n", dev->name);
+                            ret = -ENOMEM;
+                            break;
+                    }
+                    
+                    if(copy_from_user(data, xc.data, xc.len))
+                    {
+                    	kfree(data);
+                    	ret = -ENOMEM;
+                    	break;
+                    }
+
+                    printk("%s: Starting load of data Len: %d at 0x%p == 0x%p\n", dev->name, xc.len, xc.data, data);
+
+                    lmc_gpio_mkinput(sc, 0xff);
+
+                    /*
+                     * Clear the Xilinx and start prgramming from the DEC
+                     */
+
+                    /*
+                     * Set ouput as:
+                     * Reset: 0 (active)
+                     * DP:    0 (active)
+                     * Mode:  1
+                     *
+                     */
+                    sc->lmc_gpio = 0x00;
+                    sc->lmc_gpio &= ~LMC_GEP_DP;
+                    sc->lmc_gpio &= ~LMC_GEP_RESET;
+                    sc->lmc_gpio |=  LMC_GEP_MODE;
+                    LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
+
+                    lmc_gpio_mkoutput(sc, LMC_GEP_MODE | LMC_GEP_DP | LMC_GEP_RESET);
+
+                    /*
+                     * Wait at least 10 us 20 to be safe
+                     */
+                    udelay(50);
+
+                    /*
+                     * Clear reset and activate programming lines
+                     * Reset: Input
+                     * DP:    Input
+                     * Clock: Output
+                     * Data:  Output
+                     * Mode:  Output
+                     */
+                    lmc_gpio_mkinput(sc, LMC_GEP_DP | LMC_GEP_RESET);
+
+                    /*
+                     * Set LOAD, DATA, Clock to 1
+                     */
+                    sc->lmc_gpio = 0x00;
+                    sc->lmc_gpio |= LMC_GEP_MODE;
+                    sc->lmc_gpio |= LMC_GEP_DATA;
+                    sc->lmc_gpio |= LMC_GEP_CLK;
+                    LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
+                    
+                    lmc_gpio_mkoutput(sc, LMC_GEP_DATA | LMC_GEP_CLK | LMC_GEP_MODE );
+
+                    /*
+                     * busy wait for the chip to reset
+                     */
+                    while( (LMC_CSR_READ(sc, csr_gp) & LMC_GEP_INIT) == 0 &&
+                           (timeout-- > 0))
+                        ;
+
+                    printk(KERN_DEBUG "%s: Waited %d for the Xilinx to clear it's memory\n", dev->name, 500000-timeout);
+
+                    for(pos = 0; pos < xc.len; pos++){
+                        switch(data[pos]){
+                        case 0:
+                            sc->lmc_gpio &= ~LMC_GEP_DATA; /* Data is 0 */
+                            break;
+                        case 1:
+                            sc->lmc_gpio |= LMC_GEP_DATA; /* Data is 1 */
+                            break;
+                        default:
+                            printk(KERN_WARNING "%s Bad data in xilinx programming data at %d, got %d wanted 0 or 1\n", dev->name, pos, data[pos]);
+                            sc->lmc_gpio |= LMC_GEP_DATA; /* Assume it's 1 */
+                        }
+                        sc->lmc_gpio &= ~LMC_GEP_CLK; /* Clock to zero */
+                        sc->lmc_gpio |= LMC_GEP_MODE;
+                        LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
+                        udelay(1);
+                        
+                        sc->lmc_gpio |= LMC_GEP_CLK; /* Put the clack back to one */
+                        sc->lmc_gpio |= LMC_GEP_MODE;
+                        LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
+                        udelay(1);
+                    }
+                    if((LMC_CSR_READ(sc, csr_gp) & LMC_GEP_INIT) == 0){
+                        printk(KERN_WARNING "%s: Reprogramming FAILED. Needs to be reprogrammed. (corrupted data)\n", dev->name);
+                    }
+                    else if((LMC_CSR_READ(sc, csr_gp) & LMC_GEP_DP) == 0){
+                        printk(KERN_WARNING "%s: Reprogramming FAILED. Needs to be reprogrammed. (done)\n", dev->name);
+                    }
+                    else {
+                        printk(KERN_DEBUG "%s: Done reprogramming Xilinx, %d bits, good luck!\n", dev->name, pos);
+                    }
+
+                    lmc_gpio_mkinput(sc, 0xff);
+                    
+                    sc->lmc_miireg16 |= LMC_MII16_FIFO_RESET;
+                    lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+
+                    sc->lmc_miireg16 &= ~LMC_MII16_FIFO_RESET;
+                    lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+
+                    kfree(data);
+                    
+                    ret = 0;
+                    
+                    break;
+                }
+            default: /*fold02*/
+                ret = -EBADE;
+                break;
+            }
+
+            netif_wake_queue(dev);
+            sc->lmc_txfull = 0;
+
+        }
+        break;
+    default: /*fold01*/
+        /* If we don't know what to do, give the protocol a shot. */
+        ret = lmc_proto_ioctl (sc, ifr, cmd);
+        break;
+    }
+
+    spin_unlock_irqrestore(&sc->lmc_lock, flags); /*fold01*/
+
+    lmc_trace(dev, "lmc_ioctl out");
+
+    return ret;
+}
+
+
+/* the watchdog process that cruises around */
+static void lmc_watchdog (unsigned long data) /*fold00*/
+{
+    struct net_device *dev = (struct net_device *) data;
+    lmc_softc_t *sc;
+    int link_status;
+    u_int32_t ticks;
+    unsigned long flags;
+
+    sc = dev->priv;
+
+    lmc_trace(dev, "lmc_watchdog in");
+
+    spin_lock_irqsave(&sc->lmc_lock, flags);
+
+    if(sc->check != 0xBEAFCAFE){
+        printk("LMC: Corrupt net_device stuct, breaking out\n");
+	spin_unlock_irqrestore(&sc->lmc_lock, flags);
+        return;
+    }
+
+
+    /* Make sure the tx jabber and rx watchdog are off,
+     * and the transmit and receive processes are running.
+     */
+
+    LMC_CSR_WRITE (sc, csr_15, 0x00000011);
+    sc->lmc_cmdmode |= TULIP_CMD_TXRUN | TULIP_CMD_RXRUN;
+    LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode);
+
+    if (sc->lmc_ok == 0)
+        goto kick_timer;
+
+    LMC_EVENT_LOG(LMC_EVENT_WATCHDOG, LMC_CSR_READ (sc, csr_status), lmc_mii_readreg (sc, 0, 16));
+
+    /* --- begin time out check -----------------------------------
+     * check for a transmit interrupt timeout
+     * Has the packet xmt vs xmt serviced threshold been exceeded */
+    if (sc->lmc_taint_tx == sc->lastlmc_taint_tx &&
+        sc->stats.tx_packets > sc->lasttx_packets &&
+        sc->tx_TimeoutInd == 0)
+    {
+
+        /* wait for the watchdog to come around again */
+        sc->tx_TimeoutInd = 1;
+    }
+    else if (sc->lmc_taint_tx == sc->lastlmc_taint_tx &&
+             sc->stats.tx_packets > sc->lasttx_packets &&
+             sc->tx_TimeoutInd)
+    {
+
+        LMC_EVENT_LOG(LMC_EVENT_XMTINTTMO, LMC_CSR_READ (sc, csr_status), 0);
+
+        sc->tx_TimeoutDisplay = 1;
+        sc->stats.tx_TimeoutCnt++;
+
+        /* DEC chip is stuck, hit it with a RESET!!!! */
+        lmc_running_reset (dev);
+
+
+        /* look at receive & transmit process state to make sure they are running */
+        LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0);
+
+        /* look at: DSR - 02  for Reg 16
+         *                  CTS - 08
+         *                  DCD - 10
+         *                  RI  - 20
+         * for Reg 17
+         */
+        LMC_EVENT_LOG(LMC_EVENT_RESET2, lmc_mii_readreg (sc, 0, 16), lmc_mii_readreg (sc, 0, 17));
+
+        /* reset the transmit timeout detection flag */
+        sc->tx_TimeoutInd = 0;
+        sc->lastlmc_taint_tx = sc->lmc_taint_tx;
+        sc->lasttx_packets = sc->stats.tx_packets;
+    }
+    else
+    {
+        sc->tx_TimeoutInd = 0;
+        sc->lastlmc_taint_tx = sc->lmc_taint_tx;
+        sc->lasttx_packets = sc->stats.tx_packets;
+    }
+
+    /* --- end time out check ----------------------------------- */
+
+
+    link_status = sc->lmc_media->get_link_status (sc);
+
+    /*
+     * hardware level link lost, but the interface is marked as up.
+     * Mark it as down.
+     */
+    if ((link_status == 0) && (sc->last_link_status != 0)) {
+        printk(KERN_WARNING "%s: hardware/physical link down\n", dev->name);
+        sc->last_link_status = 0;
+        /* lmc_reset (sc); Why reset??? The link can go down ok */
+
+        /* Inform the world that link has been lost */
+        dev->flags &= ~IFF_RUNNING;
+    }
+
+    /*
+     * hardware link is up, but the interface is marked as down.
+     * Bring it back up again.
+     */
+     if (link_status != 0 && sc->last_link_status == 0) {
+         printk(KERN_WARNING "%s: hardware/physical link up\n", dev->name);
+         sc->last_link_status = 1;
+         /* lmc_reset (sc); Again why reset??? */
+
+         /* Inform the world that link protocol is back up. */
+         dev->flags |= IFF_RUNNING;
+
+         /* Now we have to tell the syncppp that we had an outage
+          * and that it should deal.  Calling sppp_reopen here
+          * should do the trick, but we may have to call sppp_close
+          * when the link goes down, and call sppp_open here.
+          * Subject to more testing.
+          * --bbraun
+          */
+
+         lmc_proto_reopen(sc);
+
+     }
+
+    /* Call media specific watchdog functions */
+    sc->lmc_media->watchdog(sc);
+
+    /*
+     * Poke the transmitter to make sure it
+     * never stops, even if we run out of mem
+     */
+    LMC_CSR_WRITE(sc, csr_rxpoll, 0);
+
+    /*
+     * Check for code that failed
+     * and try and fix it as appropriate
+     */
+    if(sc->failed_ring == 1){
+        /*
+         * Failed to setup the recv/xmit rin
+         * Try again
+         */
+        sc->failed_ring = 0;
+        lmc_softreset(sc);
+    }
+    if(sc->failed_recv_alloc == 1){
+        /*
+         * We failed to alloc mem in the
+         * interrupt handler, go through the rings
+         * and rebuild them
+         */
+        sc->failed_recv_alloc = 0;
+        lmc_softreset(sc);
+    }
+
+
+    /*
+     * remember the timer value
+     */
+kick_timer:
+
+    ticks = LMC_CSR_READ (sc, csr_gp_timer);
+    LMC_CSR_WRITE (sc, csr_gp_timer, 0xffffffffUL);
+    sc->ictl.ticks = 0x0000ffff - (ticks & 0x0000ffff);
+
+    /*
+     * restart this timer.
+     */
+    sc->timer.expires = jiffies + (HZ);
+    add_timer (&sc->timer);
+
+    spin_unlock_irqrestore(&sc->lmc_lock, flags);
+
+    lmc_trace(dev, "lmc_watchdog out");
+
+}
+
+static void lmc_setup(struct net_device * const dev) /*fold00*/
+{
+    lmc_trace(dev, "lmc_setup in");
+
+    dev->type = ARPHRD_HDLC;
+    dev->hard_start_xmit = lmc_start_xmit;
+    dev->open = lmc_open;
+    dev->stop = lmc_close;
+    dev->get_stats = lmc_get_stats;
+    dev->do_ioctl = lmc_ioctl;
+    dev->tx_timeout = lmc_driver_timeout;
+    dev->watchdog_timeo = (HZ); /* 1 second */
+    
+    lmc_trace(dev, "lmc_setup out");
+}
+
+
+static int __devinit lmc_init_one(struct pci_dev *pdev,
+				  const struct pci_device_id *ent)
+{
+    struct net_device *dev;
+    lmc_softc_t *sc;
+    u16 subdevice;
+    u_int16_t AdapModelNum;
+    int err = -ENOMEM;
+    static int cards_found;
+#ifndef GCOM
+    /* We name by type not by vendor */
+    static const char lmcname[] = "hdlc%d";
+#else
+    /* 
+     * GCOM uses LMC vendor name so that clients can know which card
+     * to attach to.
+     */
+    static const char lmcname[] = "lmc%d";
+#endif
+
+
+    /*
+     * Allocate our own device structure
+     */
+    dev = alloc_netdev(sizeof(lmc_softc_t), lmcname, lmc_setup);
+    if (!dev) {
+        printk (KERN_ERR "lmc:alloc_netdev for device failed\n");
+	goto out1;
+    }
+ 
+    lmc_trace(dev, "lmc_init_one in");
+
+    err = pci_enable_device(pdev);
+    if (err) {
+	    printk(KERN_ERR "lmc: pci enable failed:%d\n", err);
+	    goto out2;
+    }
+    
+    if (pci_request_regions(pdev, "lmc")) {
+	    printk(KERN_ERR "lmc: pci_request_region failed\n");
+	    err = -EIO;
+	    goto out3;
+    }
+
+    pci_set_drvdata(pdev, dev);
+
+    if(lmc_first_load == 0){
+        printk(KERN_INFO "Lan Media Corporation WAN Driver Version %d.%d.%d\n",
+	       DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION,DRIVER_SUB_VERSION);
+        lmc_first_load = 1;
+    }
+    
+    sc = dev->priv;
+    sc->lmc_device = dev;
+    sc->name = dev->name;
+
+    /* Initialize the sppp layer */
+    /* An ioctl can cause a subsequent detach for raw frame interface */
+    sc->if_type = LMC_PPP;
+    sc->check = 0xBEAFCAFE;
+    dev->base_addr = pci_resource_start(pdev, 0);
+    dev->irq = pdev->irq;
+
+    SET_MODULE_OWNER(dev);
+    SET_NETDEV_DEV(dev, &pdev->dev);
+
+    /*
+     * This will get the protocol layer ready and do any 1 time init's
+     * Must have a valid sc and dev structure
+     */
+    lmc_proto_init(sc);
+
+    lmc_proto_attach(sc);
+
+    /*
+     * Why were we changing this???
+     dev->tx_queue_len = 100;
+     */
+
+    /* Init the spin lock so can call it latter */
+
+    spin_lock_init(&sc->lmc_lock);
+    pci_set_master(pdev);
+
+    printk ("%s: detected at %lx, irq %d\n", dev->name,
+	    dev->base_addr, dev->irq);
+
+    if (register_netdev (dev) != 0) {
+        printk (KERN_ERR "%s: register_netdev failed.\n", dev->name);
+	goto out4;
+    }
+
+    sc->lmc_cardtype = LMC_CARDTYPE_UNKNOWN;
+    sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT;
+
+    /*
+     *
+     * Check either the subvendor or the subdevice, some systems reverse
+     * the setting in the bois, seems to be version and arch dependent?
+     * Fix the error, exchange the two values 
+     */
+    if ((subdevice = pdev->subsystem_device) == PCI_VENDOR_ID_LMC)
+	    subdevice = pdev->subsystem_vendor;
+
+    switch (subdevice) {
+    case PCI_DEVICE_ID_LMC_HSSI:
+        printk ("%s: LMC HSSI\n", dev->name);
+        sc->lmc_cardtype = LMC_CARDTYPE_HSSI;
+        sc->lmc_media = &lmc_hssi_media;
+        break;
+    case PCI_DEVICE_ID_LMC_DS3:
+        printk ("%s: LMC DS3\n", dev->name);
+        sc->lmc_cardtype = LMC_CARDTYPE_DS3;
+        sc->lmc_media = &lmc_ds3_media;
+        break;
+    case PCI_DEVICE_ID_LMC_SSI:
+        printk ("%s: LMC SSI\n", dev->name);
+        sc->lmc_cardtype = LMC_CARDTYPE_SSI;
+        sc->lmc_media = &lmc_ssi_media;
+        break;
+    case PCI_DEVICE_ID_LMC_T1:
+        printk ("%s: LMC T1\n", dev->name);
+        sc->lmc_cardtype = LMC_CARDTYPE_T1;
+        sc->lmc_media = &lmc_t1_media;
+        break;
+    default:
+        printk (KERN_WARNING "%s: LMC UNKOWN CARD!\n", dev->name);
+        break;
+    }
+
+    lmc_initcsrs (sc, dev->base_addr, 8);
+
+    lmc_gpio_mkinput (sc, 0xff);
+    sc->lmc_gpio = 0;		/* drive no signals yet */
+
+    sc->lmc_media->defaults (sc);
+
+    sc->lmc_media->set_link_status (sc, LMC_LINK_UP);
+
+    /* verify that the PCI Sub System ID matches the Adapter Model number
+     * from the MII register
+     */
+    AdapModelNum = (lmc_mii_readreg (sc, 0, 3) & 0x3f0) >> 4;
+
+    if ((AdapModelNum == LMC_ADAP_T1
+         && subdevice == PCI_DEVICE_ID_LMC_T1) ||	/* detect LMC1200 */
+        (AdapModelNum == LMC_ADAP_SSI
+         && subdevice == PCI_DEVICE_ID_LMC_SSI) ||	/* detect LMC1000 */
+        (AdapModelNum == LMC_ADAP_DS3
+         && subdevice == PCI_DEVICE_ID_LMC_DS3) ||	/* detect LMC5245 */
+        (AdapModelNum == LMC_ADAP_HSSI
+         && subdevice == PCI_DEVICE_ID_LMC_HSSI))
+    {				/* detect LMC5200 */
+
+    }
+    else {
+        printk ("%s: Model number (%d) miscompare for PCI Subsystem ID = 0x%04x\n",
+                dev->name, AdapModelNum, subdevice);
+//        return (NULL);
+    }
+    /*
+     * reset clock
+     */
+    LMC_CSR_WRITE (sc, csr_gp_timer, 0xFFFFFFFFUL);
+
+    sc->board_idx = cards_found++;
+    sc->stats.check = STATCHECK;
+    sc->stats.version_size = (DRIVER_VERSION << 16) +
+        sizeof (struct lmc_statistics);
+    sc->stats.lmc_cardtype = sc->lmc_cardtype;
+
+    sc->lmc_ok = 0;
+    sc->last_link_status = 0;
+
+    lmc_trace(dev, "lmc_init_one out");
+    return 0;
+
+ out4:
+    lmc_proto_detach(sc);
+ out3:
+    if (pdev) {
+	    pci_release_regions(pdev);
+	    pci_set_drvdata(pdev, NULL);
+    }
+ out2:
+    free_netdev(dev);
+ out1:
+    return err;
+}
+
+/*
+ * Called from pci when removing module.
+ */
+static void __devexit lmc_remove_one (struct pci_dev *pdev)
+{
+    struct net_device *dev = pci_get_drvdata(pdev);
+    
+    if (dev) {
+	    lmc_softc_t *sc = dev->priv;
+	    
+	    printk("%s: removing...\n", dev->name);
+	    lmc_proto_detach(sc);
+	    unregister_netdev(dev);
+	    free_netdev(dev);
+	    pci_release_regions(pdev);
+	    pci_disable_device(pdev);
+	    pci_set_drvdata(pdev, NULL);
+    }
+}
+
+/* After this is called, packets can be sent.
+ * Does not initialize the addresses
+ */
+static int lmc_open (struct net_device *dev) /*fold00*/
+{
+    lmc_softc_t *sc = dev->priv;
+
+    lmc_trace(dev, "lmc_open in");
+
+    lmc_led_on(sc, LMC_DS3_LED0);
+
+    lmc_dec_reset (sc);
+    lmc_reset (sc);
+
+    LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0);
+    LMC_EVENT_LOG(LMC_EVENT_RESET2,
+                  lmc_mii_readreg (sc, 0, 16),
+                  lmc_mii_readreg (sc, 0, 17));
+
+
+    if (sc->lmc_ok){
+        lmc_trace(dev, "lmc_open lmc_ok out");
+        return (0);
+    }
+
+    lmc_softreset (sc);
+
+    /* Since we have to use PCI bus, this should work on x86,alpha,ppc */
+    if (request_irq (dev->irq, &lmc_interrupt, SA_SHIRQ, dev->name, dev)){
+        printk(KERN_WARNING "%s: could not get irq: %d\n", dev->name, dev->irq);
+        lmc_trace(dev, "lmc_open irq failed out");
+        return -EAGAIN;
+    }
+    sc->got_irq = 1;
+
+    /* Assert Terminal Active */
+    sc->lmc_miireg16 |= LMC_MII16_LED_ALL;
+    sc->lmc_media->set_link_status (sc, LMC_LINK_UP);
+
+    /*
+     * reset to last state.
+     */
+    sc->lmc_media->set_status (sc, NULL);
+
+    /* setup default bits to be used in tulip_desc_t transmit descriptor
+     * -baz */
+    sc->TxDescriptControlInit = (
+                                 LMC_TDES_INTERRUPT_ON_COMPLETION
+                                 | LMC_TDES_FIRST_SEGMENT
+                                 | LMC_TDES_LAST_SEGMENT
+                                 | LMC_TDES_SECOND_ADDR_CHAINED
+                                 | LMC_TDES_DISABLE_PADDING
+                                );
+
+    if (sc->ictl.crc_length == LMC_CTL_CRC_LENGTH_16) {
+        /* disable 32 bit CRC generated by ASIC */
+        sc->TxDescriptControlInit |= LMC_TDES_ADD_CRC_DISABLE;
+    }
+    sc->lmc_media->set_crc_length(sc, sc->ictl.crc_length);
+    /* Acknoledge the Terminal Active and light LEDs */
+
+    /* dev->flags |= IFF_UP; */
+
+    lmc_proto_open(sc);
+
+    dev->do_ioctl = lmc_ioctl;
+
+
+    netif_start_queue(dev);
+    
+    sc->stats.tx_tbusy0++ ;
+
+    /*
+     * select what interrupts we want to get
+     */
+    sc->lmc_intrmask = 0;
+    /* Should be using the default interrupt mask defined in the .h file. */
+    sc->lmc_intrmask |= (TULIP_STS_NORMALINTR
+                         | TULIP_STS_RXINTR
+                         | TULIP_STS_TXINTR
+                         | TULIP_STS_ABNRMLINTR
+                         | TULIP_STS_SYSERROR
+                         | TULIP_STS_TXSTOPPED
+                         | TULIP_STS_TXUNDERFLOW
+                         | TULIP_STS_RXSTOPPED
+		         | TULIP_STS_RXNOBUF
+                        );
+    LMC_CSR_WRITE (sc, csr_intr, sc->lmc_intrmask);
+
+    sc->lmc_cmdmode |= TULIP_CMD_TXRUN;
+    sc->lmc_cmdmode |= TULIP_CMD_RXRUN;
+    LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode);
+
+    sc->lmc_ok = 1; /* Run watchdog */
+
+    /*
+     * Set the if up now - pfb
+     */
+
+    sc->last_link_status = 1;
+
+    /*
+     * Setup a timer for the watchdog on probe, and start it running.
+     * Since lmc_ok == 0, it will be a NOP for now.
+     */
+    init_timer (&sc->timer);
+    sc->timer.expires = jiffies + HZ;
+    sc->timer.data = (unsigned long) dev;
+    sc->timer.function = &lmc_watchdog;
+    add_timer (&sc->timer);
+
+    lmc_trace(dev, "lmc_open out");
+
+    return (0);
+}
+
+/* Total reset to compensate for the AdTran DSU doing bad things
+ *  under heavy load
+ */
+
+static void lmc_running_reset (struct net_device *dev) /*fold00*/
+{
+
+    lmc_softc_t *sc = (lmc_softc_t *) dev->priv;
+
+    lmc_trace(dev, "lmc_runnig_reset in");
+
+    /* stop interrupts */
+    /* Clear the interrupt mask */
+    LMC_CSR_WRITE (sc, csr_intr, 0x00000000);
+
+    lmc_dec_reset (sc);
+    lmc_reset (sc);
+    lmc_softreset (sc);
+    /* sc->lmc_miireg16 |= LMC_MII16_LED_ALL; */
+    sc->lmc_media->set_link_status (sc, 1);
+    sc->lmc_media->set_status (sc, NULL);
+
+    //dev->flags |= IFF_RUNNING;
+    
+    netif_wake_queue(dev);
+
+    sc->lmc_txfull = 0;
+    sc->stats.tx_tbusy0++ ;
+
+    sc->lmc_intrmask = TULIP_DEFAULT_INTR_MASK;
+    LMC_CSR_WRITE (sc, csr_intr, sc->lmc_intrmask);
+
+    sc->lmc_cmdmode |= (TULIP_CMD_TXRUN | TULIP_CMD_RXRUN);
+    LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode);
+
+    lmc_trace(dev, "lmc_runnin_reset_out");
+}
+
+
+/* This is what is called when you ifconfig down a device.
+ * This disables the timer for the watchdog and keepalives,
+ * and disables the irq for dev.
+ */
+static int lmc_close (struct net_device *dev) /*fold00*/
+{
+    /* not calling release_region() as we should */
+    lmc_softc_t *sc;
+
+    lmc_trace(dev, "lmc_close in");
+    
+    sc = dev->priv;
+    sc->lmc_ok = 0;
+    sc->lmc_media->set_link_status (sc, 0);
+    del_timer (&sc->timer);
+    lmc_proto_close(sc);
+    lmc_ifdown (dev);
+
+    lmc_trace(dev, "lmc_close out");
+    
+    return 0;
+}
+
+/* Ends the transfer of packets */
+/* When the interface goes down, this is called */
+static int lmc_ifdown (struct net_device *dev) /*fold00*/
+{
+    lmc_softc_t *sc = dev->priv;
+    u32 csr6;
+    int i;
+
+    lmc_trace(dev, "lmc_ifdown in");
+    
+    /* Don't let anything else go on right now */
+    //    dev->start = 0;
+    netif_stop_queue(dev);
+    sc->stats.tx_tbusy1++ ;
+
+    /* stop interrupts */
+    /* Clear the interrupt mask */
+    LMC_CSR_WRITE (sc, csr_intr, 0x00000000);
+
+    /* Stop Tx and Rx on the chip */
+    csr6 = LMC_CSR_READ (sc, csr_command);
+    csr6 &= ~LMC_DEC_ST;		/* Turn off the Transmission bit */
+    csr6 &= ~LMC_DEC_SR;		/* Turn off the Receive bit */
+    LMC_CSR_WRITE (sc, csr_command, csr6);
+
+    dev->flags &= ~IFF_RUNNING;
+
+    sc->stats.rx_missed_errors +=
+        LMC_CSR_READ (sc, csr_missed_frames) & 0xffff;
+
+    /* release the interrupt */
+    if(sc->got_irq == 1){
+        free_irq (dev->irq, dev);
+        sc->got_irq = 0;
+    }
+
+    /* free skbuffs in the Rx queue */
+    for (i = 0; i < LMC_RXDESCS; i++)
+    {
+        struct sk_buff *skb = sc->lmc_rxq[i];
+        sc->lmc_rxq[i] = NULL;
+        sc->lmc_rxring[i].status = 0;
+        sc->lmc_rxring[i].length = 0;
+        sc->lmc_rxring[i].buffer1 = 0xDEADBEEF;
+        if (skb != NULL)
+            dev_kfree_skb(skb);
+        sc->lmc_rxq[i] = NULL;
+    }
+
+    for (i = 0; i < LMC_TXDESCS; i++)
+    {
+        if (sc->lmc_txq[i] != NULL)
+            dev_kfree_skb(sc->lmc_txq[i]);
+        sc->lmc_txq[i] = NULL;
+    }
+
+    lmc_led_off (sc, LMC_MII16_LED_ALL);
+
+    netif_wake_queue(dev);
+    sc->stats.tx_tbusy0++ ;
+
+    lmc_trace(dev, "lmc_ifdown out");
+
+    return 0;
+}
+
+/* Interrupt handling routine.  This will take an incoming packet, or clean
+ * up after a trasmit.
+ */
+static irqreturn_t lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*fold00*/
+{
+    struct net_device *dev = (struct net_device *) dev_instance;
+    lmc_softc_t *sc;
+    u32 csr;
+    int i;
+    s32 stat;
+    unsigned int badtx;
+    u32 firstcsr;
+    int max_work = LMC_RXDESCS;
+    int handled = 0;
+
+    lmc_trace(dev, "lmc_interrupt in");
+
+    sc = dev->priv;
+    
+    spin_lock(&sc->lmc_lock);
+
+    /*
+     * Read the csr to find what interrupts we have (if any)
+     */
+    csr = LMC_CSR_READ (sc, csr_status);
+
+    /*
+     * Make sure this is our interrupt
+     */
+    if ( ! (csr & sc->lmc_intrmask)) {
+        goto lmc_int_fail_out;
+    }
+
+    firstcsr = csr;
+
+    /* always go through this loop at least once */
+    while (csr & sc->lmc_intrmask) {
+	handled = 1;
+
+        /*
+         * Clear interrupt bits, we handle all case below
+         */
+        LMC_CSR_WRITE (sc, csr_status, csr);
+
+        /*
+         * One of
+         *  - Transmit process timed out CSR5<1>
+         *  - Transmit jabber timeout    CSR5<3>
+         *  - Transmit underflow         CSR5<5>
+         *  - Transmit Receiver buffer unavailable CSR5<7>
+         *  - Receive process stopped    CSR5<8>
+         *  - Receive watchdog timeout   CSR5<9>
+         *  - Early transmit interrupt   CSR5<10>
+         *
+         * Is this really right? Should we do a running reset for jabber?
+         * (being a WAN card and all)
+         */
+        if (csr & TULIP_STS_ABNRMLINTR){
+            lmc_running_reset (dev);
+            break;
+        }
+        
+        if (csr & TULIP_STS_RXINTR){
+            lmc_trace(dev, "rx interrupt");
+            lmc_rx (dev);
+            
+        }
+        if (csr & (TULIP_STS_TXINTR | TULIP_STS_TXNOBUF | TULIP_STS_TXSTOPPED)) {
+
+	    int		n_compl = 0 ;
+            /* reset the transmit timeout detection flag -baz */
+            sc->stats.tx_NoCompleteCnt = 0;
+
+            badtx = sc->lmc_taint_tx;
+            i = badtx % LMC_TXDESCS;
+
+            while ((badtx < sc->lmc_next_tx)) {
+                stat = sc->lmc_txring[i].status;
+
+                LMC_EVENT_LOG (LMC_EVENT_XMTINT, stat,
+						 sc->lmc_txring[i].length);
+                /*
+                 * If bit 31 is 1 the tulip owns it break out of the loop
+                 */
+                if (stat & 0x80000000)
+                    break;
+
+		n_compl++ ;		/* i.e., have an empty slot in ring */
+                /*
+                 * If we have no skbuff or have cleared it
+                 * Already continue to the next buffer
+                 */
+                if (sc->lmc_txq[i] == NULL)
+                    continue;
+
+                /*
+                 * Check the total error summary to look for any errors
+                 */
+                if (stat & 0x8000) {
+                    sc->stats.tx_errors++;
+                    if (stat & 0x4104)
+                        sc->stats.tx_aborted_errors++;
+                    if (stat & 0x0C00)
+                        sc->stats.tx_carrier_errors++;
+                    if (stat & 0x0200)
+                        sc->stats.tx_window_errors++;
+                    if (stat & 0x0002)
+                        sc->stats.tx_fifo_errors++;
+                }
+                else {
+                    
+                    sc->stats.tx_bytes += sc->lmc_txring[i].length & 0x7ff;
+                    
+                    sc->stats.tx_packets++;
+                }
+                
+                //                dev_kfree_skb(sc->lmc_txq[i]);
+                dev_kfree_skb_irq(sc->lmc_txq[i]);
+                sc->lmc_txq[i] = NULL;
+
+                badtx++;
+                i = badtx % LMC_TXDESCS;
+            }
+
+            if (sc->lmc_next_tx - badtx > LMC_TXDESCS)
+            {
+                printk ("%s: out of sync pointer\n", dev->name);
+                badtx += LMC_TXDESCS;
+            }
+            LMC_EVENT_LOG(LMC_EVENT_TBUSY0, n_compl, 0);
+            sc->lmc_txfull = 0;
+            netif_wake_queue(dev);
+            sc->stats.tx_tbusy0++ ;
+
+
+#ifdef DEBUG
+            sc->stats.dirtyTx = badtx;
+            sc->stats.lmc_next_tx = sc->lmc_next_tx;
+            sc->stats.lmc_txfull = sc->lmc_txfull;
+#endif
+            sc->lmc_taint_tx = badtx;
+
+            /*
+             * Why was there a break here???
+             */
+        }			/* end handle transmit interrupt */
+
+        if (csr & TULIP_STS_SYSERROR) {
+            u32 error;
+            printk (KERN_WARNING "%s: system bus error csr: %#8.8x\n", dev->name, csr);
+            error = csr>>23 & 0x7;
+            switch(error){
+            case 0x000:
+                printk(KERN_WARNING "%s: Parity Fault (bad)\n", dev->name);
+                break;
+            case 0x001:
+                printk(KERN_WARNING "%s: Master Abort (naughty)\n", dev->name);
+                break;
+            case 0x010:
+                printk(KERN_WARNING "%s: Target Abort (not so naughty)\n", dev->name);
+                break;
+            default:
+                printk(KERN_WARNING "%s: This bus error code was supposed to be reserved!\n", dev->name);
+            }
+            lmc_dec_reset (sc);
+            lmc_reset (sc);
+            LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0);
+            LMC_EVENT_LOG(LMC_EVENT_RESET2,
+                          lmc_mii_readreg (sc, 0, 16),
+                          lmc_mii_readreg (sc, 0, 17));
+
+        }
+
+        
+        if(max_work-- <= 0)
+            break;
+        
+        /*
+         * Get current csr status to make sure
+         * we've cleared all interrupts
+         */
+        csr = LMC_CSR_READ (sc, csr_status);
+    }				/* end interrupt loop */
+    LMC_EVENT_LOG(LMC_EVENT_INT, firstcsr, csr);
+
+lmc_int_fail_out:
+
+    spin_unlock(&sc->lmc_lock);
+
+    lmc_trace(dev, "lmc_interrupt out");
+    return IRQ_RETVAL(handled);
+}
+
+static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00*/
+{
+    lmc_softc_t *sc;
+    u32 flag;
+    int entry;
+    int ret = 0;
+    unsigned long flags;
+
+    lmc_trace(dev, "lmc_start_xmit in");
+
+    sc = dev->priv;
+
+    spin_lock_irqsave(&sc->lmc_lock, flags);
+
+    /* normal path, tbusy known to be zero */
+
+    entry = sc->lmc_next_tx % LMC_TXDESCS;
+
+    sc->lmc_txq[entry] = skb;
+    sc->lmc_txring[entry].buffer1 = virt_to_bus (skb->data);
+
+    LMC_CONSOLE_LOG("xmit", skb->data, skb->len);
+
+#ifndef GCOM
+    /* If the queue is less than half full, don't interrupt */
+    if (sc->lmc_next_tx - sc->lmc_taint_tx < LMC_TXDESCS / 2)
+    {
+        /* Do not interrupt on completion of this packet */
+        flag = 0x60000000;
+        netif_wake_queue(dev);
+    }
+    else if (sc->lmc_next_tx - sc->lmc_taint_tx == LMC_TXDESCS / 2)
+    {
+        /* This generates an interrupt on completion of this packet */
+        flag = 0xe0000000;
+        netif_wake_queue(dev);
+    }
+    else if (sc->lmc_next_tx - sc->lmc_taint_tx < LMC_TXDESCS - 1)
+    {
+        /* Do not interrupt on completion of this packet */
+        flag = 0x60000000;
+        netif_wake_queue(dev);
+    }
+    else
+    {
+        /* This generates an interrupt on completion of this packet */
+        flag = 0xe0000000;
+        sc->lmc_txfull = 1;
+        netif_stop_queue(dev);
+    }
+#else
+    flag = LMC_TDES_INTERRUPT_ON_COMPLETION;
+
+    if (sc->lmc_next_tx - sc->lmc_taint_tx >= LMC_TXDESCS - 1)
+    {				/* ring full, go busy */
+        sc->lmc_txfull = 1;
+        netif_stop_queue(dev);
+        sc->stats.tx_tbusy1++ ;
+        LMC_EVENT_LOG(LMC_EVENT_TBUSY1, entry, 0);
+    }
+#endif
+
+
+    if (entry == LMC_TXDESCS - 1)	/* last descriptor in ring */
+	flag |= LMC_TDES_END_OF_RING;	/* flag as such for Tulip */
+
+    /* don't pad small packets either */
+    flag = sc->lmc_txring[entry].length = (skb->len) | flag |
+						sc->TxDescriptControlInit;
+
+    /* set the transmit timeout flag to be checked in
+     * the watchdog timer handler. -baz
+     */
+
+    sc->stats.tx_NoCompleteCnt++;
+    sc->lmc_next_tx++;
+
+    /* give ownership to the chip */
+    LMC_EVENT_LOG(LMC_EVENT_XMT, flag, entry);
+    sc->lmc_txring[entry].status = 0x80000000;
+
+    /* send now! */
+    LMC_CSR_WRITE (sc, csr_txpoll, 0);
+
+    dev->trans_start = jiffies;
+
+    spin_unlock_irqrestore(&sc->lmc_lock, flags);
+
+    lmc_trace(dev, "lmc_start_xmit_out");
+    return ret;
+}
+
+
+static int lmc_rx (struct net_device *dev) /*fold00*/
+{
+    lmc_softc_t *sc;
+    int i;
+    int rx_work_limit = LMC_RXDESCS;
+    unsigned int next_rx;
+    int rxIntLoopCnt;		/* debug -baz */
+    int localLengthErrCnt = 0;
+    long stat;
+    struct sk_buff *skb, *nsb;
+    u16 len;
+
+    lmc_trace(dev, "lmc_rx in");
+
+    sc = dev->priv;
+
+    lmc_led_on(sc, LMC_DS3_LED3);
+
+    rxIntLoopCnt = 0;		/* debug -baz */
+
+    i = sc->lmc_next_rx % LMC_RXDESCS;
+    next_rx = sc->lmc_next_rx;
+
+    while (((stat = sc->lmc_rxring[i].status) & LMC_RDES_OWN_BIT) != DESC_OWNED_BY_DC21X4)
+    {
+        rxIntLoopCnt++;		/* debug -baz */
+        len = ((stat & LMC_RDES_FRAME_LENGTH) >> RDES_FRAME_LENGTH_BIT_NUMBER);
+        if ((stat & 0x0300) != 0x0300) {  /* Check first segment and last segment */
+            if ((stat & 0x0000ffff) != 0x7fff) {
+                /* Oversized frame */
+                sc->stats.rx_length_errors++;
+                goto skip_packet;
+            }
+        }
+
+        if(stat & 0x00000008){ /* Catch a dribbling bit error */
+            sc->stats.rx_errors++;
+            sc->stats.rx_frame_errors++;
+            goto skip_packet;
+        }
+
+
+        if(stat & 0x00000004){ /* Catch a CRC error by the Xilinx */
+            sc->stats.rx_errors++;
+            sc->stats.rx_crc_errors++;
+            goto skip_packet;
+        }
+
+
+        if (len > LMC_PKT_BUF_SZ){
+            sc->stats.rx_length_errors++;
+            localLengthErrCnt++;
+            goto skip_packet;
+        }
+
+        if (len < sc->lmc_crcSize + 2) {
+            sc->stats.rx_length_errors++;
+            sc->stats.rx_SmallPktCnt++;
+            localLengthErrCnt++;
+            goto skip_packet;
+        }
+
+        if(stat & 0x00004000){
+            printk(KERN_WARNING "%s: Receiver descriptor error, receiver out of sync?\n", dev->name);
+        }
+
+        len -= sc->lmc_crcSize;
+
+        skb = sc->lmc_rxq[i];
+
+        /*
+         * We ran out of memory at some point
+         * just allocate an skb buff and continue.
+         */
+        
+        if(skb == 0x0){
+            nsb = dev_alloc_skb (LMC_PKT_BUF_SZ + 2);
+            if (nsb) {
+                sc->lmc_rxq[i] = nsb;
+                nsb->dev = dev;
+                sc->lmc_rxring[i].buffer1 = virt_to_bus (nsb->tail);
+            }
+            sc->failed_recv_alloc = 1;
+            goto skip_packet;
+        }
+        
+        dev->last_rx = jiffies;
+        sc->stats.rx_packets++;
+        sc->stats.rx_bytes += len;
+
+        LMC_CONSOLE_LOG("recv", skb->data, len);
+
+        /*
+         * I'm not sure of the sanity of this
+         * Packets could be arriving at a constant
+         * 44.210mbits/sec and we're going to copy
+         * them into a new buffer??
+         */
+        
+        if(len > (LMC_MTU - (LMC_MTU>>2))){ /* len > LMC_MTU * 0.75 */
+            /*
+             * If it's a large packet don't copy it just hand it up
+             */
+        give_it_anyways:
+
+            sc->lmc_rxq[i] = NULL;
+            sc->lmc_rxring[i].buffer1 = 0x0;
+
+            skb_put (skb, len);
+            skb->protocol = lmc_proto_type(sc, skb);
+            skb->protocol = htons(ETH_P_WAN_PPP);
+            skb->mac.raw = skb->data;
+//            skb->nh.raw = skb->data;
+            skb->dev = dev;
+            lmc_proto_netif(sc, skb);
+
+            /*
+             * This skb will be destroyed by the upper layers, make a new one
+             */
+            nsb = dev_alloc_skb (LMC_PKT_BUF_SZ + 2);
+            if (nsb) {
+                sc->lmc_rxq[i] = nsb;
+                nsb->dev = dev;
+                sc->lmc_rxring[i].buffer1 = virt_to_bus (nsb->tail);
+                /* Transferred to 21140 below */
+            }
+            else {
+                /*
+                 * We've run out of memory, stop trying to allocate
+                 * memory and exit the interrupt handler
+                 *
+                 * The chip may run out of receivers and stop
+                 * in which care we'll try to allocate the buffer
+                 * again.  (once a second)
+                 */
+                sc->stats.rx_BuffAllocErr++;
+                LMC_EVENT_LOG(LMC_EVENT_RCVINT, stat, len);
+                sc->failed_recv_alloc = 1;
+                goto skip_out_of_mem;
+            }
+        }
+        else {
+            nsb = dev_alloc_skb(len);
+            if(!nsb) {
+                goto give_it_anyways;
+            }
+            memcpy(skb_put(nsb, len), skb->data, len);
+            
+            nsb->protocol = lmc_proto_type(sc, skb);
+            nsb->mac.raw = nsb->data;
+//            nsb->nh.raw = nsb->data;
+            nsb->dev = dev;
+            lmc_proto_netif(sc, nsb);
+        }
+
+    skip_packet:
+        LMC_EVENT_LOG(LMC_EVENT_RCVINT, stat, len);
+        sc->lmc_rxring[i].status = DESC_OWNED_BY_DC21X4;
+
+        sc->lmc_next_rx++;
+        i = sc->lmc_next_rx % LMC_RXDESCS;
+        rx_work_limit--;
+        if (rx_work_limit < 0)
+            break;
+    }
+
+    /* detect condition for LMC1000 where DSU cable attaches and fills
+     * descriptors with bogus packets
+     *
+    if (localLengthErrCnt > LMC_RXDESCS - 3) {
+        sc->stats.rx_BadPktSurgeCnt++;
+        LMC_EVENT_LOG(LMC_EVENT_BADPKTSURGE,
+                      localLengthErrCnt,
+                      sc->stats.rx_BadPktSurgeCnt);
+    } */
+
+    /* save max count of receive descriptors serviced */
+    if (rxIntLoopCnt > sc->stats.rxIntLoopCnt) {
+        sc->stats.rxIntLoopCnt = rxIntLoopCnt;	/* debug -baz */
+    }
+
+#ifdef DEBUG
+    if (rxIntLoopCnt == 0)
+    {
+        for (i = 0; i < LMC_RXDESCS; i++)
+        {
+            if ((sc->lmc_rxring[i].status & LMC_RDES_OWN_BIT)
+                != DESC_OWNED_BY_DC21X4)
+            {
+                rxIntLoopCnt++;
+            }
+        }
+        LMC_EVENT_LOG(LMC_EVENT_RCVEND, rxIntLoopCnt, 0);
+    }
+#endif
+
+
+    lmc_led_off(sc, LMC_DS3_LED3);
+
+skip_out_of_mem:
+
+    lmc_trace(dev, "lmc_rx out");
+
+    return 0;
+}
+
+static struct net_device_stats *lmc_get_stats (struct net_device *dev) /*fold00*/
+{
+    lmc_softc_t *sc = dev->priv;
+    unsigned long flags;
+
+    lmc_trace(dev, "lmc_get_stats in");
+
+
+    spin_lock_irqsave(&sc->lmc_lock, flags);
+
+    sc->stats.rx_missed_errors += LMC_CSR_READ (sc, csr_missed_frames) & 0xffff;
+
+    spin_unlock_irqrestore(&sc->lmc_lock, flags);
+
+    lmc_trace(dev, "lmc_get_stats out");
+
+    return (struct net_device_stats *) &sc->stats;
+}
+
+static struct pci_driver lmc_driver = {
+	.name		= "lmc",
+	.id_table	= lmc_pci_tbl,
+	.probe		= lmc_init_one,
+	.remove		= __devexit_p(lmc_remove_one),
+};
+
+static int __init init_lmc(void)
+{
+    return pci_module_init(&lmc_driver);
+}
+
+static void __exit exit_lmc(void)
+{
+    pci_unregister_driver(&lmc_driver);
+}
+
+module_init(init_lmc);
+module_exit(exit_lmc);
+
+unsigned lmc_mii_readreg (lmc_softc_t * const sc, unsigned devaddr, unsigned regno) /*fold00*/
+{
+    int i;
+    int command = (0xf6 << 10) | (devaddr << 5) | regno;
+    int retval = 0;
+
+    lmc_trace(sc->lmc_device, "lmc_mii_readreg in");
+
+    LMC_MII_SYNC (sc);
+
+    lmc_trace(sc->lmc_device, "lmc_mii_readreg: done sync");
+
+    for (i = 15; i >= 0; i--)
+    {
+        int dataval = (command & (1 << i)) ? 0x20000 : 0;
+
+        LMC_CSR_WRITE (sc, csr_9, dataval);
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+        LMC_CSR_WRITE (sc, csr_9, dataval | 0x10000);
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+    }
+
+    lmc_trace(sc->lmc_device, "lmc_mii_readreg: done1");
+
+    for (i = 19; i > 0; i--)
+    {
+        LMC_CSR_WRITE (sc, csr_9, 0x40000);
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+        retval = (retval << 1) | ((LMC_CSR_READ (sc, csr_9) & 0x80000) ? 1 : 0);
+        LMC_CSR_WRITE (sc, csr_9, 0x40000 | 0x10000);
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+    }
+
+    lmc_trace(sc->lmc_device, "lmc_mii_readreg out");
+
+    return (retval >> 1) & 0xffff;
+}
+
+void lmc_mii_writereg (lmc_softc_t * const sc, unsigned devaddr, unsigned regno, unsigned data) /*fold00*/
+{
+    int i = 32;
+    int command = (0x5002 << 16) | (devaddr << 23) | (regno << 18) | data;
+
+    lmc_trace(sc->lmc_device, "lmc_mii_writereg in");
+
+    LMC_MII_SYNC (sc);
+
+    i = 31;
+    while (i >= 0)
+    {
+        int datav;
+
+        if (command & (1 << i))
+            datav = 0x20000;
+        else
+            datav = 0x00000;
+
+        LMC_CSR_WRITE (sc, csr_9, datav);
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+        LMC_CSR_WRITE (sc, csr_9, (datav | 0x10000));
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+        i--;
+    }
+
+    i = 2;
+    while (i > 0)
+    {
+        LMC_CSR_WRITE (sc, csr_9, 0x40000);
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+        LMC_CSR_WRITE (sc, csr_9, 0x50000);
+        lmc_delay ();
+        /* __SLOW_DOWN_IO; */
+        i--;
+    }
+
+    lmc_trace(sc->lmc_device, "lmc_mii_writereg out");
+}
+
+static void lmc_softreset (lmc_softc_t * const sc) /*fold00*/
+{
+    int i;
+
+    lmc_trace(sc->lmc_device, "lmc_softreset in");
+
+    /* Initialize the receive rings and buffers. */
+    sc->lmc_txfull = 0;
+    sc->lmc_next_rx = 0;
+    sc->lmc_next_tx = 0;
+    sc->lmc_taint_rx = 0;
+    sc->lmc_taint_tx = 0;
+
+    /*
+     * Setup each one of the receiver buffers
+     * allocate an skbuff for each one, setup the descriptor table
+     * and point each buffer at the next one
+     */
+
+    for (i = 0; i < LMC_RXDESCS; i++)
+    {
+        struct sk_buff *skb;
+
+        if (sc->lmc_rxq[i] == NULL)
+        {
+            skb = dev_alloc_skb (LMC_PKT_BUF_SZ + 2);
+            if(skb == NULL){
+                printk(KERN_WARNING "%s: Failed to allocate receiver ring, will try again\n", sc->name);
+                sc->failed_ring = 1;
+                break;
+            }
+            else{
+                sc->lmc_rxq[i] = skb;
+            }
+        }
+        else
+        {
+            skb = sc->lmc_rxq[i];
+        }
+
+        skb->dev = sc->lmc_device;
+
+        /* owned by 21140 */
+        sc->lmc_rxring[i].status = 0x80000000;
+
+        /* used to be PKT_BUF_SZ now uses skb since we lose some to head room */
+        sc->lmc_rxring[i].length = skb->end - skb->data;
+
+        /* use to be tail which is dumb since you're thinking why write
+         * to the end of the packj,et but since there's nothing there tail == data
+         */
+        sc->lmc_rxring[i].buffer1 = virt_to_bus (skb->data);
+
+        /* This is fair since the structure is static and we have the next address */
+        sc->lmc_rxring[i].buffer2 = virt_to_bus (&sc->lmc_rxring[i + 1]);
+
+    }
+
+    /*
+     * Sets end of ring
+     */
+    sc->lmc_rxring[i - 1].length |= 0x02000000; /* Set end of buffers flag */
+    sc->lmc_rxring[i - 1].buffer2 = virt_to_bus (&sc->lmc_rxring[0]); /* Point back to the start */
+    LMC_CSR_WRITE (sc, csr_rxlist, virt_to_bus (sc->lmc_rxring)); /* write base address */
+
+
+    /* Initialize the transmit rings and buffers */
+    for (i = 0; i < LMC_TXDESCS; i++)
+    {
+        if (sc->lmc_txq[i] != NULL){		/* have buffer */
+            dev_kfree_skb(sc->lmc_txq[i]);	/* free it */
+            sc->stats.tx_dropped++;      /* We just dropped a packet */
+        }
+        sc->lmc_txq[i] = NULL;
+        sc->lmc_txring[i].status = 0x00000000;
+        sc->lmc_txring[i].buffer2 = virt_to_bus (&sc->lmc_txring[i + 1]);
+    }
+    sc->lmc_txring[i - 1].buffer2 = virt_to_bus (&sc->lmc_txring[0]);
+    LMC_CSR_WRITE (sc, csr_txlist, virt_to_bus (sc->lmc_txring));
+
+    lmc_trace(sc->lmc_device, "lmc_softreset out");
+}
+
+void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_gpio_mkinput in");
+    sc->lmc_gpio_io &= ~bits;
+    LMC_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET | (sc->lmc_gpio_io));
+    lmc_trace(sc->lmc_device, "lmc_gpio_mkinput out");
+}
+
+void lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_gpio_mkoutput in");
+    sc->lmc_gpio_io |= bits;
+    LMC_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET | (sc->lmc_gpio_io));
+    lmc_trace(sc->lmc_device, "lmc_gpio_mkoutput out");
+}
+
+void lmc_led_on(lmc_softc_t * const sc, u_int32_t led) /*fold00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_led_on in");
+    if((~sc->lmc_miireg16) & led){ /* Already on! */
+        lmc_trace(sc->lmc_device, "lmc_led_on aon out");
+        return;
+    }
+    
+    sc->lmc_miireg16 &= ~led;
+    lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+    lmc_trace(sc->lmc_device, "lmc_led_on out");
+}
+
+void lmc_led_off(lmc_softc_t * const sc, u_int32_t led) /*fold00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_led_off in");
+    if(sc->lmc_miireg16 & led){ /* Already set don't do anything */
+        lmc_trace(sc->lmc_device, "lmc_led_off aoff out");
+        return;
+    }
+    
+    sc->lmc_miireg16 |= led;
+    lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+    lmc_trace(sc->lmc_device, "lmc_led_off out");
+}
+
+static void lmc_reset(lmc_softc_t * const sc) /*fold00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_reset in");
+    sc->lmc_miireg16 |= LMC_MII16_FIFO_RESET;
+    lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+
+    sc->lmc_miireg16 &= ~LMC_MII16_FIFO_RESET;
+    lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+
+    /*
+     * make some of the GPIO pins be outputs
+     */
+    lmc_gpio_mkoutput(sc, LMC_GEP_RESET);
+
+    /*
+     * RESET low to force state reset.  This also forces
+     * the transmitter clock to be internal, but we expect to reset
+     * that later anyway.
+     */
+    sc->lmc_gpio &= ~(LMC_GEP_RESET);
+    LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);
+
+    /*
+     * hold for more than 10 microseconds
+     */
+    udelay(50);
+
+    /*
+     * stop driving Xilinx-related signals
+     */
+    lmc_gpio_mkinput(sc, LMC_GEP_RESET);
+
+    /*
+     * Call media specific init routine
+     */
+    sc->lmc_media->init(sc);
+
+    sc->stats.resetCount++;
+    lmc_trace(sc->lmc_device, "lmc_reset out");
+}
+
+static void lmc_dec_reset(lmc_softc_t * const sc) /*fold00*/
+{
+    u_int32_t val;
+    lmc_trace(sc->lmc_device, "lmc_dec_reset in");
+
+    /*
+     * disable all interrupts
+     */
+    sc->lmc_intrmask = 0;
+    LMC_CSR_WRITE(sc, csr_intr, sc->lmc_intrmask);
+
+    /*
+     * Reset the chip with a software reset command.
+     * Wait 10 microseconds (actually 50 PCI cycles but at
+     * 33MHz that comes to two microseconds but wait a
+     * bit longer anyways)
+     */
+    LMC_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
+    udelay(25);
+#ifdef __sparc__
+    sc->lmc_busmode = LMC_CSR_READ(sc, csr_busmode);
+    sc->lmc_busmode = 0x00100000;
+    sc->lmc_busmode &= ~TULIP_BUSMODE_SWRESET;
+    LMC_CSR_WRITE(sc, csr_busmode, sc->lmc_busmode);
+#endif
+    sc->lmc_cmdmode = LMC_CSR_READ(sc, csr_command);
+
+    /*
+     * We want:
+     *   no ethernet address in frames we write
+     *   disable padding (txdesc, padding disable)
+     *   ignore runt frames (rdes0 bit 15)
+     *   no receiver watchdog or transmitter jabber timer
+     *       (csr15 bit 0,14 == 1)
+     *   if using 16-bit CRC, turn off CRC (trans desc, crc disable)
+     */
+
+    sc->lmc_cmdmode |= ( TULIP_CMD_PROMISCUOUS
+                         | TULIP_CMD_FULLDUPLEX
+                         | TULIP_CMD_PASSBADPKT
+                         | TULIP_CMD_NOHEARTBEAT
+                         | TULIP_CMD_PORTSELECT
+                         | TULIP_CMD_RECEIVEALL
+                         | TULIP_CMD_MUSTBEONE
+                       );
+    sc->lmc_cmdmode &= ~( TULIP_CMD_OPERMODE
+                          | TULIP_CMD_THRESHOLDCTL
+                          | TULIP_CMD_STOREFWD
+                          | TULIP_CMD_TXTHRSHLDCTL
+                        );
+
+    LMC_CSR_WRITE(sc, csr_command, sc->lmc_cmdmode);
+
+    /*
+     * disable receiver watchdog and transmit jabber
+     */
+    val = LMC_CSR_READ(sc, csr_sia_general);
+    val |= (TULIP_WATCHDOG_TXDISABLE | TULIP_WATCHDOG_RXDISABLE);
+    LMC_CSR_WRITE(sc, csr_sia_general, val);
+
+    lmc_trace(sc->lmc_device, "lmc_dec_reset out");
+}
+
+static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, /*fold00*/
+                         size_t csr_size)
+{
+    lmc_trace(sc->lmc_device, "lmc_initcsrs in");
+    sc->lmc_csrs.csr_busmode	        = csr_base +  0 * csr_size;
+    sc->lmc_csrs.csr_txpoll		= csr_base +  1 * csr_size;
+    sc->lmc_csrs.csr_rxpoll		= csr_base +  2 * csr_size;
+    sc->lmc_csrs.csr_rxlist		= csr_base +  3 * csr_size;
+    sc->lmc_csrs.csr_txlist		= csr_base +  4 * csr_size;
+    sc->lmc_csrs.csr_status		= csr_base +  5 * csr_size;
+    sc->lmc_csrs.csr_command	        = csr_base +  6 * csr_size;
+    sc->lmc_csrs.csr_intr		= csr_base +  7 * csr_size;
+    sc->lmc_csrs.csr_missed_frames	= csr_base +  8 * csr_size;
+    sc->lmc_csrs.csr_9		        = csr_base +  9 * csr_size;
+    sc->lmc_csrs.csr_10		        = csr_base + 10 * csr_size;
+    sc->lmc_csrs.csr_11		        = csr_base + 11 * csr_size;
+    sc->lmc_csrs.csr_12		        = csr_base + 12 * csr_size;
+    sc->lmc_csrs.csr_13		        = csr_base + 13 * csr_size;
+    sc->lmc_csrs.csr_14		        = csr_base + 14 * csr_size;
+    sc->lmc_csrs.csr_15		        = csr_base + 15 * csr_size;
+    lmc_trace(sc->lmc_device, "lmc_initcsrs out");
+}
+
+static void lmc_driver_timeout(struct net_device *dev) { /*fold00*/
+    lmc_softc_t *sc;
+    u32 csr6;
+    unsigned long flags;
+
+    lmc_trace(dev, "lmc_driver_timeout in");
+
+    sc = dev->priv;
+
+    spin_lock_irqsave(&sc->lmc_lock, flags);
+
+    printk("%s: Xmitter busy|\n", dev->name);
+
+    sc->stats.tx_tbusy_calls++ ;
+    if (jiffies - dev->trans_start < TX_TIMEOUT) {
+        goto bug_out;
+    }
+
+    /*
+     * Chip seems to have locked up
+     * Reset it
+     * This whips out all our decriptor
+     * table and starts from scartch
+     */
+
+    LMC_EVENT_LOG(LMC_EVENT_XMTPRCTMO,
+                  LMC_CSR_READ (sc, csr_status),
+                  sc->stats.tx_ProcTimeout);
+
+    lmc_running_reset (dev);
+
+    LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0);
+    LMC_EVENT_LOG(LMC_EVENT_RESET2,
+                  lmc_mii_readreg (sc, 0, 16),
+                  lmc_mii_readreg (sc, 0, 17));
+
+    /* restart the tx processes */
+    csr6 = LMC_CSR_READ (sc, csr_command);
+    LMC_CSR_WRITE (sc, csr_command, csr6 | 0x0002);
+    LMC_CSR_WRITE (sc, csr_command, csr6 | 0x2002);
+
+    /* immediate transmit */
+    LMC_CSR_WRITE (sc, csr_txpoll, 0);
+
+    sc->stats.tx_errors++;
+    sc->stats.tx_ProcTimeout++;	/* -baz */
+
+    dev->trans_start = jiffies;
+
+bug_out:
+
+    spin_unlock_irqrestore(&sc->lmc_lock, flags);
+
+    lmc_trace(dev, "lmc_driver_timout out");
+
+
+}
diff --git a/drivers/net/wan/lmc/lmc_media.c b/drivers/net/wan/lmc/lmc_media.c
new file mode 100644
index 0000000..f55ce76
--- /dev/null
+++ b/drivers/net/wan/lmc/lmc_media.c
@@ -0,0 +1,1246 @@
+/* $Id: lmc_media.c,v 1.13 2000/04/11 05:25:26 asj Exp $ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/in.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/inet.h>
+#include <linux/bitops.h>
+
+#include <net/syncppp.h>
+
+#include <asm/processor.h>             /* Processor type for cache alignment. */
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <asm/uaccess.h>
+
+#include "lmc.h"
+#include "lmc_var.h"
+#include "lmc_ioctl.h"
+#include "lmc_debug.h"
+
+#define CONFIG_LMC_IGNORE_HARDWARE_HANDSHAKE 1
+
+ /*
+  * Copyright (c) 1997-2000 LAN Media Corporation (LMC)
+  * All rights reserved.  www.lanmedia.com
+  *
+  * This code is written by:
+  * Andrew Stanley-Jones (asj@cban.com)
+  * Rob Braun (bbraun@vix.com),
+  * Michael Graff (explorer@vix.com) and
+  * Matt Thomas (matt@3am-software.com).
+  *
+  * This software may be used and distributed according to the terms
+  * of the GNU General Public License version 2, incorporated herein by reference.
+  */
+
+/*
+ * For lack of a better place, put the SSI cable stuff here.
+ */
+char *lmc_t1_cables[] = {
+  "V.10/RS423", "EIA530A", "reserved", "X.21", "V.35",
+  "EIA449/EIA530/V.36", "V.28/EIA232", "none", NULL
+};
+
+/*
+ * protocol independent method.
+ */
+static void lmc_set_protocol (lmc_softc_t * const, lmc_ctl_t *);
+
+/*
+ * media independent methods to check on media status, link, light LEDs,
+ * etc.
+ */
+static void lmc_ds3_init (lmc_softc_t * const);
+static void lmc_ds3_default (lmc_softc_t * const);
+static void lmc_ds3_set_status (lmc_softc_t * const, lmc_ctl_t *);
+static void lmc_ds3_set_100ft (lmc_softc_t * const, int);
+static int lmc_ds3_get_link_status (lmc_softc_t * const);
+static void lmc_ds3_set_crc_length (lmc_softc_t * const, int);
+static void lmc_ds3_set_scram (lmc_softc_t * const, int);
+static void lmc_ds3_watchdog (lmc_softc_t * const);
+
+static void lmc_hssi_init (lmc_softc_t * const);
+static void lmc_hssi_default (lmc_softc_t * const);
+static void lmc_hssi_set_status (lmc_softc_t * const, lmc_ctl_t *);
+static void lmc_hssi_set_clock (lmc_softc_t * const, int);
+static int lmc_hssi_get_link_status (lmc_softc_t * const);
+static void lmc_hssi_set_link_status (lmc_softc_t * const, int);
+static void lmc_hssi_set_crc_length (lmc_softc_t * const, int);
+static void lmc_hssi_watchdog (lmc_softc_t * const);
+
+static void lmc_ssi_init (lmc_softc_t * const);
+static void lmc_ssi_default (lmc_softc_t * const);
+static void lmc_ssi_set_status (lmc_softc_t * const, lmc_ctl_t *);
+static void lmc_ssi_set_clock (lmc_softc_t * const, int);
+static void lmc_ssi_set_speed (lmc_softc_t * const, lmc_ctl_t *);
+static int lmc_ssi_get_link_status (lmc_softc_t * const);
+static void lmc_ssi_set_link_status (lmc_softc_t * const, int);
+static void lmc_ssi_set_crc_length (lmc_softc_t * const, int);
+static void lmc_ssi_watchdog (lmc_softc_t * const);
+
+static void lmc_t1_init (lmc_softc_t * const);
+static void lmc_t1_default (lmc_softc_t * const);
+static void lmc_t1_set_status (lmc_softc_t * const, lmc_ctl_t *);
+static int lmc_t1_get_link_status (lmc_softc_t * const);
+static void lmc_t1_set_circuit_type (lmc_softc_t * const, int);
+static void lmc_t1_set_crc_length (lmc_softc_t * const, int);
+static void lmc_t1_set_clock (lmc_softc_t * const, int);
+static void lmc_t1_watchdog (lmc_softc_t * const);
+
+static void lmc_dummy_set_1 (lmc_softc_t * const, int);
+static void lmc_dummy_set2_1 (lmc_softc_t * const, lmc_ctl_t *);
+
+static inline void write_av9110_bit (lmc_softc_t *, int);
+static void write_av9110 (lmc_softc_t *, u_int32_t, u_int32_t, u_int32_t,
+			  u_int32_t, u_int32_t);
+
+lmc_media_t lmc_ds3_media = {
+  lmc_ds3_init,			/* special media init stuff */
+  lmc_ds3_default,		/* reset to default state */
+  lmc_ds3_set_status,		/* reset status to state provided */
+  lmc_dummy_set_1,		/* set clock source */
+  lmc_dummy_set2_1,		/* set line speed */
+  lmc_ds3_set_100ft,		/* set cable length */
+  lmc_ds3_set_scram,		/* set scrambler */
+  lmc_ds3_get_link_status,	/* get link status */
+  lmc_dummy_set_1,		/* set link status */
+  lmc_ds3_set_crc_length,	/* set CRC length */
+  lmc_dummy_set_1,		/* set T1 or E1 circuit type */
+  lmc_ds3_watchdog
+};
+
+lmc_media_t lmc_hssi_media = {
+  lmc_hssi_init,		/* special media init stuff */
+  lmc_hssi_default,		/* reset to default state */
+  lmc_hssi_set_status,		/* reset status to state provided */
+  lmc_hssi_set_clock,		/* set clock source */
+  lmc_dummy_set2_1,		/* set line speed */
+  lmc_dummy_set_1,		/* set cable length */
+  lmc_dummy_set_1,		/* set scrambler */
+  lmc_hssi_get_link_status,	/* get link status */
+  lmc_hssi_set_link_status,	/* set link status */
+  lmc_hssi_set_crc_length,	/* set CRC length */
+  lmc_dummy_set_1,		/* set T1 or E1 circuit type */
+  lmc_hssi_watchdog
+};
+
+lmc_media_t lmc_ssi_media = { lmc_ssi_init,	/* special media init stuff */
+  lmc_ssi_default,		/* reset to default state */
+  lmc_ssi_set_status,		/* reset status to state provided */
+  lmc_ssi_set_clock,		/* set clock source */
+  lmc_ssi_set_speed,		/* set line speed */
+  lmc_dummy_set_1,		/* set cable length */
+  lmc_dummy_set_1,		/* set scrambler */
+  lmc_ssi_get_link_status,	/* get link status */
+  lmc_ssi_set_link_status,	/* set link status */
+  lmc_ssi_set_crc_length,	/* set CRC length */
+  lmc_dummy_set_1,		/* set T1 or E1 circuit type */
+  lmc_ssi_watchdog
+};
+
+lmc_media_t lmc_t1_media = {
+  lmc_t1_init,			/* special media init stuff */
+  lmc_t1_default,		/* reset to default state */
+  lmc_t1_set_status,		/* reset status to state provided */
+  lmc_t1_set_clock,		/* set clock source */
+  lmc_dummy_set2_1,		/* set line speed */
+  lmc_dummy_set_1,		/* set cable length */
+  lmc_dummy_set_1,		/* set scrambler */
+  lmc_t1_get_link_status,	/* get link status */
+  lmc_dummy_set_1,		/* set link status */
+  lmc_t1_set_crc_length,	/* set CRC length */
+  lmc_t1_set_circuit_type,	/* set T1 or E1 circuit type */
+  lmc_t1_watchdog
+};
+
+static void
+lmc_dummy_set_1 (lmc_softc_t * const sc, int a)
+{
+}
+
+static void
+lmc_dummy_set2_1 (lmc_softc_t * const sc, lmc_ctl_t * a)
+{
+}
+
+/*
+ *  HSSI methods
+ */
+
+static void
+lmc_hssi_init (lmc_softc_t * const sc)
+{
+  sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC5200;
+
+  lmc_gpio_mkoutput (sc, LMC_GEP_HSSI_CLOCK);
+}
+
+static void
+lmc_hssi_default (lmc_softc_t * const sc)
+{
+  sc->lmc_miireg16 = LMC_MII16_LED_ALL;
+
+  sc->lmc_media->set_link_status (sc, LMC_LINK_DOWN);
+  sc->lmc_media->set_clock_source (sc, LMC_CTL_CLOCK_SOURCE_EXT);
+  sc->lmc_media->set_crc_length (sc, LMC_CTL_CRC_LENGTH_16);
+}
+
+/*
+ * Given a user provided state, set ourselves up to match it.  This will
+ * always reset the card if needed.
+ */
+static void
+lmc_hssi_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+{
+  if (ctl == NULL)
+    {
+      sc->lmc_media->set_clock_source (sc, sc->ictl.clock_source);
+      lmc_set_protocol (sc, NULL);
+
+      return;
+    }
+
+  /*
+   * check for change in clock source
+   */
+  if (ctl->clock_source && !sc->ictl.clock_source)
+    {
+      sc->lmc_media->set_clock_source (sc, LMC_CTL_CLOCK_SOURCE_INT);
+      sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_INT;
+    }
+  else if (!ctl->clock_source && sc->ictl.clock_source)
+    {
+      sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT;
+      sc->lmc_media->set_clock_source (sc, LMC_CTL_CLOCK_SOURCE_EXT);
+    }
+
+  lmc_set_protocol (sc, ctl);
+}
+
+/*
+ * 1 == internal, 0 == external
+ */
+static void
+lmc_hssi_set_clock (lmc_softc_t * const sc, int ie)
+{
+  int old;
+  old = sc->ictl.clock_source;
+  if (ie == LMC_CTL_CLOCK_SOURCE_EXT)
+    {
+      sc->lmc_gpio |= LMC_GEP_HSSI_CLOCK;
+      LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+      sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_EXT;
+      if(old != ie)
+        printk (LMC_PRINTF_FMT ": clock external\n", LMC_PRINTF_ARGS);
+    }
+  else
+    {
+      sc->lmc_gpio &= ~(LMC_GEP_HSSI_CLOCK);
+      LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+      sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT;
+      if(old != ie)
+        printk (LMC_PRINTF_FMT ": clock internal\n", LMC_PRINTF_ARGS);
+    }
+}
+
+/*
+ * return hardware link status.
+ * 0 == link is down, 1 == link is up.
+ */
+static int
+lmc_hssi_get_link_status (lmc_softc_t * const sc)
+{
+    /*
+     * We're using the same code as SSI since
+     * they're practically the same
+     */
+    return lmc_ssi_get_link_status(sc);
+}
+
+static void
+lmc_hssi_set_link_status (lmc_softc_t * const sc, int state)
+{
+  if (state == LMC_LINK_UP)
+    sc->lmc_miireg16 |= LMC_MII16_HSSI_TA;
+  else
+    sc->lmc_miireg16 &= ~LMC_MII16_HSSI_TA;
+
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+}
+
+/*
+ * 0 == 16bit, 1 == 32bit
+ */
+static void
+lmc_hssi_set_crc_length (lmc_softc_t * const sc, int state)
+{
+  if (state == LMC_CTL_CRC_LENGTH_32)
+    {
+      /* 32 bit */
+      sc->lmc_miireg16 |= LMC_MII16_HSSI_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32;
+    }
+  else
+    {
+      /* 16 bit */
+      sc->lmc_miireg16 &= ~LMC_MII16_HSSI_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16;
+    }
+
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+}
+
+static void
+lmc_hssi_watchdog (lmc_softc_t * const sc)
+{
+  /* HSSI is blank */
+}
+
+/*
+ *  DS3 methods
+ */
+
+/*
+ * Set cable length
+ */
+static void
+lmc_ds3_set_100ft (lmc_softc_t * const sc, int ie)
+{
+  if (ie == LMC_CTL_CABLE_LENGTH_GT_100FT)
+    {
+      sc->lmc_miireg16 &= ~LMC_MII16_DS3_ZERO;
+      sc->ictl.cable_length = LMC_CTL_CABLE_LENGTH_GT_100FT;
+    }
+  else if (ie == LMC_CTL_CABLE_LENGTH_LT_100FT)
+    {
+      sc->lmc_miireg16 |= LMC_MII16_DS3_ZERO;
+      sc->ictl.cable_length = LMC_CTL_CABLE_LENGTH_LT_100FT;
+    }
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+}
+
+static void
+lmc_ds3_default (lmc_softc_t * const sc)
+{
+  sc->lmc_miireg16 = LMC_MII16_LED_ALL;
+
+  sc->lmc_media->set_link_status (sc, LMC_LINK_DOWN);
+  sc->lmc_media->set_cable_length (sc, LMC_CTL_CABLE_LENGTH_LT_100FT);
+  sc->lmc_media->set_scrambler (sc, LMC_CTL_OFF);
+  sc->lmc_media->set_crc_length (sc, LMC_CTL_CRC_LENGTH_16);
+}
+
+/*
+ * Given a user provided state, set ourselves up to match it.  This will
+ * always reset the card if needed.
+ */
+static void
+lmc_ds3_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+{
+  if (ctl == NULL)
+    {
+      sc->lmc_media->set_cable_length (sc, sc->ictl.cable_length);
+      sc->lmc_media->set_scrambler (sc, sc->ictl.scrambler_onoff);
+      lmc_set_protocol (sc, NULL);
+
+      return;
+    }
+
+  /*
+   * check for change in cable length setting
+   */
+  if (ctl->cable_length && !sc->ictl.cable_length)
+    lmc_ds3_set_100ft (sc, LMC_CTL_CABLE_LENGTH_GT_100FT);
+  else if (!ctl->cable_length && sc->ictl.cable_length)
+    lmc_ds3_set_100ft (sc, LMC_CTL_CABLE_LENGTH_LT_100FT);
+
+  /*
+   * Check for change in scrambler setting (requires reset)
+   */
+  if (ctl->scrambler_onoff && !sc->ictl.scrambler_onoff)
+    lmc_ds3_set_scram (sc, LMC_CTL_ON);
+  else if (!ctl->scrambler_onoff && sc->ictl.scrambler_onoff)
+    lmc_ds3_set_scram (sc, LMC_CTL_OFF);
+
+  lmc_set_protocol (sc, ctl);
+}
+
+static void
+lmc_ds3_init (lmc_softc_t * const sc)
+{
+  int i;
+
+  sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC5245;
+
+  /* writes zeros everywhere */
+  for (i = 0; i < 21; i++)
+    {
+      lmc_mii_writereg (sc, 0, 17, i);
+      lmc_mii_writereg (sc, 0, 18, 0);
+    }
+
+  /* set some essential bits */
+  lmc_mii_writereg (sc, 0, 17, 1);
+  lmc_mii_writereg (sc, 0, 18, 0x25);	/* ser, xtx */
+
+  lmc_mii_writereg (sc, 0, 17, 5);
+  lmc_mii_writereg (sc, 0, 18, 0x80);	/* emode */
+
+  lmc_mii_writereg (sc, 0, 17, 14);
+  lmc_mii_writereg (sc, 0, 18, 0x30);	/* rcgen, tcgen */
+
+  /* clear counters and latched bits */
+  for (i = 0; i < 21; i++)
+    {
+      lmc_mii_writereg (sc, 0, 17, i);
+      lmc_mii_readreg (sc, 0, 18);
+    }
+}
+
+/*
+ * 1 == DS3 payload scrambled, 0 == not scrambled
+ */
+static void
+lmc_ds3_set_scram (lmc_softc_t * const sc, int ie)
+{
+  if (ie == LMC_CTL_ON)
+    {
+      sc->lmc_miireg16 |= LMC_MII16_DS3_SCRAM;
+      sc->ictl.scrambler_onoff = LMC_CTL_ON;
+    }
+  else
+    {
+      sc->lmc_miireg16 &= ~LMC_MII16_DS3_SCRAM;
+      sc->ictl.scrambler_onoff = LMC_CTL_OFF;
+    }
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+}
+
+/*
+ * return hardware link status.
+ * 0 == link is down, 1 == link is up.
+ */
+static int
+lmc_ds3_get_link_status (lmc_softc_t * const sc)
+{
+    u_int16_t link_status, link_status_11;
+    int ret = 1;
+
+    lmc_mii_writereg (sc, 0, 17, 7);
+    link_status = lmc_mii_readreg (sc, 0, 18);
+
+    /* LMC5245 (DS3) & LMC1200 (DS1) LED definitions
+     * led0 yellow = far-end adapter is in Red alarm condition
+     * led1 blue   = received an Alarm Indication signal
+     *               (upstream failure)
+     * led2 Green  = power to adapter, Gate Array loaded & driver
+     *               attached
+     * led3 red    = Loss of Signal (LOS) or out of frame (OOF)
+     *               conditions detected on T3 receive signal
+     */
+
+    lmc_led_on(sc, LMC_DS3_LED2);
+
+    if ((link_status & LMC_FRAMER_REG0_DLOS) ||
+        (link_status & LMC_FRAMER_REG0_OOFS)){
+        ret = 0;
+        if(sc->last_led_err[3] != 1){
+            u16 r1;
+            lmc_mii_writereg (sc, 0, 17, 01); /* Turn on Xbit error as our cisco does */
+            r1 = lmc_mii_readreg (sc, 0, 18);
+            r1 &= 0xfe;
+            lmc_mii_writereg(sc, 0, 18, r1);
+            printk(KERN_WARNING "%s: Red Alarm - Loss of Signal or Loss of Framing\n", sc->name);
+        }
+        lmc_led_on(sc, LMC_DS3_LED3);	/* turn on red LED */
+        sc->last_led_err[3] = 1;
+    }
+    else {
+        lmc_led_off(sc, LMC_DS3_LED3);	/* turn on red LED */
+        if(sc->last_led_err[3] == 1){
+            u16 r1;
+            lmc_mii_writereg (sc, 0, 17, 01); /* Turn off Xbit error */
+            r1 = lmc_mii_readreg (sc, 0, 18);
+            r1 |= 0x01;
+            lmc_mii_writereg(sc, 0, 18, r1);
+        }
+        sc->last_led_err[3] = 0;
+    }
+
+    lmc_mii_writereg(sc, 0, 17, 0x10);
+    link_status_11 = lmc_mii_readreg(sc, 0, 18);
+    if((link_status & LMC_FRAMER_REG0_AIS) ||
+       (link_status_11 & LMC_FRAMER_REG10_XBIT)) {
+        ret = 0;
+        if(sc->last_led_err[0] != 1){
+            printk(KERN_WARNING "%s: AIS Alarm or XBit Error\n", sc->name);
+            printk(KERN_WARNING "%s: Remote end has loss of signal or framing\n", sc->name);
+        }
+        lmc_led_on(sc, LMC_DS3_LED0);
+        sc->last_led_err[0] = 1;
+    }
+    else {
+        lmc_led_off(sc, LMC_DS3_LED0);
+        sc->last_led_err[0] = 0;
+    }
+
+    lmc_mii_writereg (sc, 0, 17, 9);
+    link_status = lmc_mii_readreg (sc, 0, 18);
+    
+    if(link_status & LMC_FRAMER_REG9_RBLUE){
+        ret = 0;
+        if(sc->last_led_err[1] != 1){
+            printk(KERN_WARNING "%s: Blue Alarm - Receiving all 1's\n", sc->name);
+        }
+        lmc_led_on(sc, LMC_DS3_LED1);
+        sc->last_led_err[1] = 1;
+    }
+    else {
+        lmc_led_off(sc, LMC_DS3_LED1);
+        sc->last_led_err[1] = 0;
+    }
+
+    return ret;
+}
+
+/*
+ * 0 == 16bit, 1 == 32bit
+ */
+static void
+lmc_ds3_set_crc_length (lmc_softc_t * const sc, int state)
+{
+  if (state == LMC_CTL_CRC_LENGTH_32)
+    {
+      /* 32 bit */
+      sc->lmc_miireg16 |= LMC_MII16_DS3_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32;
+    }
+  else
+    {
+      /* 16 bit */
+      sc->lmc_miireg16 &= ~LMC_MII16_DS3_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16;
+    }
+
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+}
+
+static void
+lmc_ds3_watchdog (lmc_softc_t * const sc)
+{
+    
+}
+
+
+/*
+ *  SSI methods
+ */
+
+static void
+lmc_ssi_init (lmc_softc_t * const sc)
+{
+  u_int16_t mii17;
+  int cable;
+
+  sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC1000;
+
+  mii17 = lmc_mii_readreg (sc, 0, 17);
+
+  cable = (mii17 & LMC_MII17_SSI_CABLE_MASK) >> LMC_MII17_SSI_CABLE_SHIFT;
+  sc->ictl.cable_type = cable;
+
+  lmc_gpio_mkoutput (sc, LMC_GEP_SSI_TXCLOCK);
+}
+
+static void
+lmc_ssi_default (lmc_softc_t * const sc)
+{
+  sc->lmc_miireg16 = LMC_MII16_LED_ALL;
+
+  /*
+   * make TXCLOCK always be an output
+   */
+  lmc_gpio_mkoutput (sc, LMC_GEP_SSI_TXCLOCK);
+
+  sc->lmc_media->set_link_status (sc, LMC_LINK_DOWN);
+  sc->lmc_media->set_clock_source (sc, LMC_CTL_CLOCK_SOURCE_EXT);
+  sc->lmc_media->set_speed (sc, NULL);
+  sc->lmc_media->set_crc_length (sc, LMC_CTL_CRC_LENGTH_16);
+}
+
+/*
+ * Given a user provided state, set ourselves up to match it.  This will
+ * always reset the card if needed.
+ */
+static void
+lmc_ssi_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+{
+  if (ctl == NULL)
+    {
+      sc->lmc_media->set_clock_source (sc, sc->ictl.clock_source);
+      sc->lmc_media->set_speed (sc, &sc->ictl);
+      lmc_set_protocol (sc, NULL);
+
+      return;
+    }
+
+  /*
+   * check for change in clock source
+   */
+  if (ctl->clock_source == LMC_CTL_CLOCK_SOURCE_INT
+      && sc->ictl.clock_source == LMC_CTL_CLOCK_SOURCE_EXT)
+    {
+      sc->lmc_media->set_clock_source (sc, LMC_CTL_CLOCK_SOURCE_INT);
+      sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_INT;
+    }
+  else if (ctl->clock_source == LMC_CTL_CLOCK_SOURCE_EXT
+	   && sc->ictl.clock_source == LMC_CTL_CLOCK_SOURCE_INT)
+    {
+      sc->lmc_media->set_clock_source (sc, LMC_CTL_CLOCK_SOURCE_EXT);
+      sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT;
+    }
+
+  if (ctl->clock_rate != sc->ictl.clock_rate)
+    sc->lmc_media->set_speed (sc, ctl);
+
+  lmc_set_protocol (sc, ctl);
+}
+
+/*
+ * 1 == internal, 0 == external
+ */
+static void
+lmc_ssi_set_clock (lmc_softc_t * const sc, int ie)
+{
+  int old;
+  old = ie;
+  if (ie == LMC_CTL_CLOCK_SOURCE_EXT)
+    {
+      sc->lmc_gpio &= ~(LMC_GEP_SSI_TXCLOCK);
+      LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+      sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_EXT;
+      if(ie != old)
+        printk (LMC_PRINTF_FMT ": clock external\n", LMC_PRINTF_ARGS);
+    }
+  else
+    {
+      sc->lmc_gpio |= LMC_GEP_SSI_TXCLOCK;
+      LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+      sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT;
+      if(ie != old)
+        printk (LMC_PRINTF_FMT ": clock internal\n", LMC_PRINTF_ARGS);
+    }
+}
+
+static void
+lmc_ssi_set_speed (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+{
+  lmc_ctl_t *ictl = &sc->ictl;
+  lmc_av9110_t *av;
+
+  /* original settings for clock rate of:
+   *  100 Khz (8,25,0,0,2) were incorrect
+   *  they should have been 80,125,1,3,3
+   *  There are 17 param combinations to produce this freq.
+   *  For 1.5 Mhz use 120,100,1,1,2 (226 param. combinations)
+   */
+  if (ctl == NULL)
+    {
+      av = &ictl->cardspec.ssi;
+      ictl->clock_rate = 1500000;
+      av->f = ictl->clock_rate;
+      av->n = 120;
+      av->m = 100;
+      av->v = 1;
+      av->x = 1;
+      av->r = 2;
+
+      write_av9110 (sc, av->n, av->m, av->v, av->x, av->r);
+      return;
+    }
+
+  av = &ctl->cardspec.ssi;
+
+  if (av->f == 0)
+    return;
+
+  ictl->clock_rate = av->f;	/* really, this is the rate we are */
+  ictl->cardspec.ssi = *av;
+
+  write_av9110 (sc, av->n, av->m, av->v, av->x, av->r);
+}
+
+/*
+ * return hardware link status.
+ * 0 == link is down, 1 == link is up.
+ */
+static int
+lmc_ssi_get_link_status (lmc_softc_t * const sc)
+{
+  u_int16_t link_status;
+  u_int32_t ticks;
+  int ret = 1;
+  int hw_hdsk = 1;
+  
+  /*
+   * missing CTS?  Hmm.  If we require CTS on, we may never get the
+   * link to come up, so omit it in this test.
+   *
+   * Also, it seems that with a loopback cable, DCD isn't asserted,
+   * so just check for things like this:
+   *      DSR _must_ be asserted.
+   *      One of DCD or CTS must be asserted.
+   */
+
+  /* LMC 1000 (SSI) LED definitions
+   * led0 Green = power to adapter, Gate Array loaded &
+   *              driver attached
+   * led1 Green = DSR and DTR and RTS and CTS are set
+   * led2 Green = Cable detected
+   * led3 red   = No timing is available from the
+   *              cable or the on-board frequency
+   *              generator.
+   */
+
+  link_status = lmc_mii_readreg (sc, 0, 16);
+
+  /* Is the transmit clock still available */
+  ticks = LMC_CSR_READ (sc, csr_gp_timer);
+  ticks = 0x0000ffff - (ticks & 0x0000ffff);
+
+  lmc_led_on (sc, LMC_MII16_LED0);
+
+  /* ====== transmit clock determination ===== */
+  if (sc->lmc_timing == LMC_CTL_CLOCK_SOURCE_INT) {
+      lmc_led_off(sc, LMC_MII16_LED3);
+  }
+  else if (ticks == 0 ) {				/* no clock found ? */
+      ret = 0;
+      if(sc->last_led_err[3] != 1){
+          sc->stats.tx_lossOfClockCnt++;
+          printk(KERN_WARNING "%s: Lost Clock, Link Down\n", sc->name);
+      }
+      sc->last_led_err[3] = 1;
+      lmc_led_on (sc, LMC_MII16_LED3);	/* turn ON red LED */
+  }
+  else {
+      if(sc->last_led_err[3] == 1)
+          printk(KERN_WARNING "%s: Clock Returned\n", sc->name);
+      sc->last_led_err[3] = 0;
+      lmc_led_off (sc, LMC_MII16_LED3);		/* turn OFF red LED */
+  }
+
+  if ((link_status & LMC_MII16_SSI_DSR) == 0) { /* Also HSSI CA */
+      ret = 0;
+      hw_hdsk = 0;
+  }
+
+#ifdef CONFIG_LMC_IGNORE_HARDWARE_HANDSHAKE
+  if ((link_status & (LMC_MII16_SSI_CTS | LMC_MII16_SSI_DCD)) == 0){
+      ret = 0;
+      hw_hdsk = 0;
+  }
+#endif
+
+  if(hw_hdsk == 0){
+      if(sc->last_led_err[1] != 1)
+          printk(KERN_WARNING "%s: DSR not asserted\n", sc->name);
+      sc->last_led_err[1] = 1;
+      lmc_led_off(sc, LMC_MII16_LED1);
+  }
+  else {
+      if(sc->last_led_err[1] != 0)
+          printk(KERN_WARNING "%s: DSR now asserted\n", sc->name);
+      sc->last_led_err[1] = 0;
+      lmc_led_on(sc, LMC_MII16_LED1);
+  }
+
+  if(ret == 1) {
+      lmc_led_on(sc, LMC_MII16_LED2); /* Over all good status? */
+  }
+  
+  return ret;
+}
+
+static void
+lmc_ssi_set_link_status (lmc_softc_t * const sc, int state)
+{
+  if (state == LMC_LINK_UP)
+    {
+      sc->lmc_miireg16 |= (LMC_MII16_SSI_DTR | LMC_MII16_SSI_RTS);
+      printk (LMC_PRINTF_FMT ": asserting DTR and RTS\n", LMC_PRINTF_ARGS);
+    }
+  else
+    {
+      sc->lmc_miireg16 &= ~(LMC_MII16_SSI_DTR | LMC_MII16_SSI_RTS);
+      printk (LMC_PRINTF_FMT ": deasserting DTR and RTS\n", LMC_PRINTF_ARGS);
+    }
+
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+
+}
+
+/*
+ * 0 == 16bit, 1 == 32bit
+ */
+static void
+lmc_ssi_set_crc_length (lmc_softc_t * const sc, int state)
+{
+  if (state == LMC_CTL_CRC_LENGTH_32)
+    {
+      /* 32 bit */
+      sc->lmc_miireg16 |= LMC_MII16_SSI_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32;
+      sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_4;
+
+    }
+  else
+    {
+      /* 16 bit */
+      sc->lmc_miireg16 &= ~LMC_MII16_SSI_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16;
+      sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_2;
+    }
+
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+}
+
+/*
+ * These are bits to program the ssi frequency generator
+ */
+static inline void
+write_av9110_bit (lmc_softc_t * sc, int c)
+{
+  /*
+   * set the data bit as we need it.
+   */
+  sc->lmc_gpio &= ~(LMC_GEP_CLK);
+  if (c & 0x01)
+    sc->lmc_gpio |= LMC_GEP_DATA;
+  else
+    sc->lmc_gpio &= ~(LMC_GEP_DATA);
+  LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+
+  /*
+   * set the clock to high
+   */
+  sc->lmc_gpio |= LMC_GEP_CLK;
+  LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+
+  /*
+   * set the clock to low again.
+   */
+  sc->lmc_gpio &= ~(LMC_GEP_CLK);
+  LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+}
+
+static void
+write_av9110 (lmc_softc_t * sc, u_int32_t n, u_int32_t m, u_int32_t v,
+	      u_int32_t x, u_int32_t r)
+{
+  int i;
+
+#if 0
+  printk (LMC_PRINTF_FMT ": speed %u, %d %d %d %d %d\n",
+	  LMC_PRINTF_ARGS, sc->ictl.clock_rate, n, m, v, x, r);
+#endif
+
+  sc->lmc_gpio |= LMC_GEP_SSI_GENERATOR;
+  sc->lmc_gpio &= ~(LMC_GEP_DATA | LMC_GEP_CLK);
+  LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+
+  /*
+   * Set the TXCLOCK, GENERATOR, SERIAL, and SERIALCLK
+   * as outputs.
+   */
+  lmc_gpio_mkoutput (sc, (LMC_GEP_DATA | LMC_GEP_CLK
+			  | LMC_GEP_SSI_GENERATOR));
+
+  sc->lmc_gpio &= ~(LMC_GEP_SSI_GENERATOR);
+  LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+
+  /*
+   * a shifting we will go...
+   */
+  for (i = 0; i < 7; i++)
+    write_av9110_bit (sc, n >> i);
+  for (i = 0; i < 7; i++)
+    write_av9110_bit (sc, m >> i);
+  for (i = 0; i < 1; i++)
+    write_av9110_bit (sc, v >> i);
+  for (i = 0; i < 2; i++)
+    write_av9110_bit (sc, x >> i);
+  for (i = 0; i < 2; i++)
+    write_av9110_bit (sc, r >> i);
+  for (i = 0; i < 5; i++)
+    write_av9110_bit (sc, 0x17 >> i);
+
+  /*
+   * stop driving serial-related signals
+   */
+  lmc_gpio_mkinput (sc,
+		    (LMC_GEP_DATA | LMC_GEP_CLK
+		     | LMC_GEP_SSI_GENERATOR));
+}
+
+static void
+lmc_ssi_watchdog (lmc_softc_t * const sc)
+{
+  u_int16_t mii17;
+  struct ssicsr2
+  {
+    unsigned short dtr:1, dsr:1, rts:1, cable:3, crc:1, led0:1, led1:1,
+      led2:1, led3:1, fifo:1, ll:1, rl:1, tm:1, loop:1;
+  };
+  struct ssicsr2 *ssicsr;
+  mii17 = lmc_mii_readreg (sc, 0, 17);
+  ssicsr = (struct ssicsr2 *) &mii17;
+  if (ssicsr->cable == 7)
+    {
+      lmc_led_off (sc, LMC_MII16_LED2);
+    }
+  else
+    {
+      lmc_led_on (sc, LMC_MII16_LED2);
+    }
+
+}
+
+/*
+ *  T1 methods
+ */
+
+/*
+ * The framer regs are multiplexed through MII regs 17 & 18
+ *  write the register address to MII reg 17 and the *  data to MII reg 18. */
+static void
+lmc_t1_write (lmc_softc_t * const sc, int a, int d)
+{
+  lmc_mii_writereg (sc, 0, 17, a);
+  lmc_mii_writereg (sc, 0, 18, d);
+}
+
+/* Save a warning
+static int
+lmc_t1_read (lmc_softc_t * const sc, int a)
+{
+  lmc_mii_writereg (sc, 0, 17, a);
+  return lmc_mii_readreg (sc, 0, 18);
+}
+*/
+
+
+static void
+lmc_t1_init (lmc_softc_t * const sc)
+{
+  u_int16_t mii16;
+  int i;
+
+  sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC1200;
+  mii16 = lmc_mii_readreg (sc, 0, 16);
+
+  /* reset 8370 */
+  mii16 &= ~LMC_MII16_T1_RST;
+  lmc_mii_writereg (sc, 0, 16, mii16 | LMC_MII16_T1_RST);
+  lmc_mii_writereg (sc, 0, 16, mii16);
+
+  /* set T1 or E1 line.  Uses sc->lmcmii16 reg in function so update it */
+  sc->lmc_miireg16 = mii16;
+  lmc_t1_set_circuit_type(sc, LMC_CTL_CIRCUIT_TYPE_T1);
+  mii16 = sc->lmc_miireg16;
+
+  lmc_t1_write (sc, 0x01, 0x1B);	/* CR0     - primary control             */
+  lmc_t1_write (sc, 0x02, 0x42);	/* JAT_CR  - jitter atten config         */
+  lmc_t1_write (sc, 0x14, 0x00);	/* LOOP    - loopback config             */
+  lmc_t1_write (sc, 0x15, 0x00);	/* DL3_TS  - external data link timeslot */
+  lmc_t1_write (sc, 0x18, 0xFF);	/* PIO     - programmable I/O            */
+  lmc_t1_write (sc, 0x19, 0x30);	/* POE     - programmable OE             */
+  lmc_t1_write (sc, 0x1A, 0x0F);	/* CMUX    - clock input mux             */
+  lmc_t1_write (sc, 0x20, 0x41);	/* LIU_CR  - RX LIU config               */
+  lmc_t1_write (sc, 0x22, 0x76);	/* RLIU_CR - RX LIU config               */
+  lmc_t1_write (sc, 0x40, 0x03);	/* RCR0    - RX config                   */
+  lmc_t1_write (sc, 0x45, 0x00);	/* RALM    - RX alarm config             */
+  lmc_t1_write (sc, 0x46, 0x05);	/* LATCH   - RX alarm/err/cntr latch     */
+  lmc_t1_write (sc, 0x68, 0x40);	/* TLIU_CR - TX LIU config               */
+  lmc_t1_write (sc, 0x70, 0x0D);	/* TCR0    - TX framer config            */
+  lmc_t1_write (sc, 0x71, 0x05);	/* TCR1    - TX config                   */
+  lmc_t1_write (sc, 0x72, 0x0B);	/* TFRM    - TX frame format             */
+  lmc_t1_write (sc, 0x73, 0x00);	/* TERROR  - TX error insert             */
+  lmc_t1_write (sc, 0x74, 0x00);	/* TMAN    - TX manual Sa/FEBE config    */
+  lmc_t1_write (sc, 0x75, 0x00);	/* TALM    - TX alarm signal config      */
+  lmc_t1_write (sc, 0x76, 0x00);	/* TPATT   - TX test pattern config      */
+  lmc_t1_write (sc, 0x77, 0x00);	/* TLB     - TX inband loopback config   */
+  lmc_t1_write (sc, 0x90, 0x05);	/* CLAD_CR - clock rate adapter config   */
+  lmc_t1_write (sc, 0x91, 0x05);	/* CSEL    - clad freq sel               */
+  lmc_t1_write (sc, 0xA6, 0x00);	/* DL1_CTL - DL1 control                 */
+  lmc_t1_write (sc, 0xB1, 0x00);	/* DL2_CTL - DL2 control                 */
+  lmc_t1_write (sc, 0xD0, 0x47);	/* SBI_CR  - sys bus iface config        */
+  lmc_t1_write (sc, 0xD1, 0x70);	/* RSB_CR  - RX sys bus config           */
+  lmc_t1_write (sc, 0xD4, 0x30);	/* TSB_CR  - TX sys bus config           */
+  for (i = 0; i < 32; i++)
+    {
+      lmc_t1_write (sc, 0x0E0 + i, 0x00);	/* SBCn - sys bus per-channel ctl    */
+      lmc_t1_write (sc, 0x100 + i, 0x00);	/* TPCn - TX per-channel ctl         */
+      lmc_t1_write (sc, 0x180 + i, 0x00);	/* RPCn - RX per-channel ctl         */
+    }
+  for (i = 1; i < 25; i++)
+    {
+      lmc_t1_write (sc, 0x0E0 + i, 0x0D);	/* SBCn - sys bus per-channel ctl    */
+    }
+
+  mii16 |= LMC_MII16_T1_XOE;
+  lmc_mii_writereg (sc, 0, 16, mii16);
+  sc->lmc_miireg16 = mii16;
+}
+
+static void
+lmc_t1_default (lmc_softc_t * const sc)
+{
+  sc->lmc_miireg16 = LMC_MII16_LED_ALL;
+  sc->lmc_media->set_link_status (sc, LMC_LINK_DOWN);
+  sc->lmc_media->set_circuit_type (sc, LMC_CTL_CIRCUIT_TYPE_T1);
+  sc->lmc_media->set_crc_length (sc, LMC_CTL_CRC_LENGTH_16);
+  /* Right now we can only clock from out internal source */
+  sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT;
+}
+/* * Given a user provided state, set ourselves up to match it.  This will * always reset the card if needed.
+ */
+static void
+lmc_t1_set_status (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+{
+  if (ctl == NULL)
+    {
+      sc->lmc_media->set_circuit_type (sc, sc->ictl.circuit_type);
+      lmc_set_protocol (sc, NULL);
+
+      return;
+    }
+  /*
+   * check for change in circuit type         */
+  if (ctl->circuit_type == LMC_CTL_CIRCUIT_TYPE_T1
+      && sc->ictl.circuit_type ==
+      LMC_CTL_CIRCUIT_TYPE_E1) sc->lmc_media->set_circuit_type (sc,
+								LMC_CTL_CIRCUIT_TYPE_E1);
+  else if (ctl->circuit_type == LMC_CTL_CIRCUIT_TYPE_E1
+	   && sc->ictl.circuit_type == LMC_CTL_CIRCUIT_TYPE_T1)
+    sc->lmc_media->set_circuit_type (sc, LMC_CTL_CIRCUIT_TYPE_T1);
+  lmc_set_protocol (sc, ctl);
+}
+/*
+ * return hardware link status.
+ * 0 == link is down, 1 == link is up.
+ */ static int
+lmc_t1_get_link_status (lmc_softc_t * const sc)
+{
+    u_int16_t link_status;
+    int ret = 1;
+
+  /* LMC5245 (DS3) & LMC1200 (DS1) LED definitions
+   * led0 yellow = far-end adapter is in Red alarm condition
+   * led1 blue   = received an Alarm Indication signal
+   *               (upstream failure)
+   * led2 Green  = power to adapter, Gate Array loaded & driver
+   *               attached
+   * led3 red    = Loss of Signal (LOS) or out of frame (OOF)
+   *               conditions detected on T3 receive signal
+   */
+    lmc_trace(sc->lmc_device, "lmc_t1_get_link_status in");
+    lmc_led_on(sc, LMC_DS3_LED2);
+
+    lmc_mii_writereg (sc, 0, 17, T1FRAMER_ALARM1_STATUS);
+    link_status = lmc_mii_readreg (sc, 0, 18);
+
+
+    if (link_status & T1F_RAIS) {			/* turn on blue LED */
+        ret = 0;
+        if(sc->last_led_err[1] != 1){
+            printk(KERN_WARNING "%s: Receive AIS/Blue Alarm. Far end in RED alarm\n", sc->name);
+        }
+        lmc_led_on(sc, LMC_DS3_LED1);
+        sc->last_led_err[1] = 1;
+    }
+    else {
+        if(sc->last_led_err[1] != 0){
+            printk(KERN_WARNING "%s: End AIS/Blue Alarm\n", sc->name);
+        }
+        lmc_led_off (sc, LMC_DS3_LED1);
+        sc->last_led_err[1] = 0;
+    }
+
+    /*
+     * Yellow Alarm is nasty evil stuff, looks at data patterns
+     * inside the channel and confuses it with HDLC framing
+     * ignore all yellow alarms.
+     *
+     * Do listen to MultiFrame Yellow alarm which while implemented
+     * different ways isn't in the channel and hence somewhat
+     * more reliable
+     */
+
+    if (link_status & T1F_RMYEL) {
+        ret = 0;
+        if(sc->last_led_err[0] != 1){
+            printk(KERN_WARNING "%s: Receive Yellow AIS Alarm\n", sc->name);
+        }
+        lmc_led_on(sc, LMC_DS3_LED0);
+        sc->last_led_err[0] = 1;
+    }
+    else {
+        if(sc->last_led_err[0] != 0){
+            printk(KERN_WARNING "%s: End of Yellow AIS Alarm\n", sc->name);
+        }
+        lmc_led_off(sc, LMC_DS3_LED0);
+        sc->last_led_err[0] = 0;
+    }
+
+    /*
+     * Loss of signal and los of frame
+     * Use the green bit to identify which one lit the led
+     */
+    if(link_status & T1F_RLOF){
+        ret = 0;
+        if(sc->last_led_err[3] != 1){
+            printk(KERN_WARNING "%s: Local Red Alarm: Loss of Framing\n", sc->name);
+        }
+        lmc_led_on(sc, LMC_DS3_LED3);
+        sc->last_led_err[3] = 1;
+
+    }
+    else {
+        if(sc->last_led_err[3] != 0){
+            printk(KERN_WARNING "%s: End Red Alarm (LOF)\n", sc->name);
+        }
+        if( ! (link_status & T1F_RLOS))
+            lmc_led_off(sc, LMC_DS3_LED3);
+        sc->last_led_err[3] = 0;
+    }
+    
+    if(link_status & T1F_RLOS){
+        ret = 0;
+        if(sc->last_led_err[2] != 1){
+            printk(KERN_WARNING "%s: Local Red Alarm: Loss of Signal\n", sc->name);
+        }
+        lmc_led_on(sc, LMC_DS3_LED3);
+        sc->last_led_err[2] = 1;
+
+    }
+    else {
+        if(sc->last_led_err[2] != 0){
+            printk(KERN_WARNING "%s: End Red Alarm (LOS)\n", sc->name);
+        }
+        if( ! (link_status & T1F_RLOF))
+            lmc_led_off(sc, LMC_DS3_LED3);
+        sc->last_led_err[2] = 0;
+    }
+
+    sc->lmc_xinfo.t1_alarm1_status = link_status;
+
+    lmc_mii_writereg (sc, 0, 17, T1FRAMER_ALARM2_STATUS);
+    sc->lmc_xinfo.t1_alarm2_status = lmc_mii_readreg (sc, 0, 18);
+
+    
+    lmc_trace(sc->lmc_device, "lmc_t1_get_link_status out");
+
+    return ret;
+}
+
+/*
+ * 1 == T1 Circuit Type , 0 == E1 Circuit Type
+ */
+static void
+lmc_t1_set_circuit_type (lmc_softc_t * const sc, int ie)
+{
+  if (ie == LMC_CTL_CIRCUIT_TYPE_T1) {
+      sc->lmc_miireg16 |= LMC_MII16_T1_Z;
+      sc->ictl.circuit_type = LMC_CTL_CIRCUIT_TYPE_T1;
+      printk(KERN_INFO "%s: In T1 Mode\n", sc->name);
+  }
+  else {
+      sc->lmc_miireg16 &= ~LMC_MII16_T1_Z;
+      sc->ictl.circuit_type = LMC_CTL_CIRCUIT_TYPE_E1;
+      printk(KERN_INFO "%s: In E1 Mode\n", sc->name);
+  }
+
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+  
+}
+
+/*
+ * 0 == 16bit, 1 == 32bit */
+static void
+lmc_t1_set_crc_length (lmc_softc_t * const sc, int state)
+{
+  if (state == LMC_CTL_CRC_LENGTH_32)
+    {
+      /* 32 bit */
+      sc->lmc_miireg16 |= LMC_MII16_T1_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_32;
+      sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_4;
+
+    }
+  else
+    {
+      /* 16 bit */ sc->lmc_miireg16 &= ~LMC_MII16_T1_CRC;
+      sc->ictl.crc_length = LMC_CTL_CRC_LENGTH_16;
+      sc->lmc_crcSize = LMC_CTL_CRC_BYTESIZE_2;
+
+    }
+
+  lmc_mii_writereg (sc, 0, 16, sc->lmc_miireg16);
+}
+
+/*
+ * 1 == internal, 0 == external
+ */
+static void
+lmc_t1_set_clock (lmc_softc_t * const sc, int ie)
+{
+  int old;
+  old = ie;
+  if (ie == LMC_CTL_CLOCK_SOURCE_EXT)
+    {
+      sc->lmc_gpio &= ~(LMC_GEP_SSI_TXCLOCK);
+      LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+      sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_EXT;
+      if(old != ie)
+        printk (LMC_PRINTF_FMT ": clock external\n", LMC_PRINTF_ARGS);
+    }
+  else
+    {
+      sc->lmc_gpio |= LMC_GEP_SSI_TXCLOCK;
+      LMC_CSR_WRITE (sc, csr_gp, sc->lmc_gpio);
+      sc->ictl.clock_source = LMC_CTL_CLOCK_SOURCE_INT;
+      if(old != ie)
+        printk (LMC_PRINTF_FMT ": clock internal\n", LMC_PRINTF_ARGS);
+    }
+}
+
+static void
+lmc_t1_watchdog (lmc_softc_t * const sc)
+{
+}
+
+static void
+lmc_set_protocol (lmc_softc_t * const sc, lmc_ctl_t * ctl)
+{
+  if (ctl == 0)
+    {
+      sc->ictl.keepalive_onoff = LMC_CTL_ON;
+
+      return;
+    }
+}
diff --git a/drivers/net/wan/lmc/lmc_media.h b/drivers/net/wan/lmc/lmc_media.h
new file mode 100644
index 0000000..ddcc004
--- /dev/null
+++ b/drivers/net/wan/lmc/lmc_media.h
@@ -0,0 +1,65 @@
+#ifndef _LMC_MEDIA_H_
+#define _LMC_MEDIA_H_
+
+lmc_media_t lmc_ds3_media = {
+  lmc_ds3_init,			/* special media init stuff */
+  lmc_ds3_default,		/* reset to default state */
+  lmc_ds3_set_status,		/* reset status to state provided */
+  lmc_dummy_set_1,		/* set clock source */
+  lmc_dummy_set2_1,		/* set line speed */
+  lmc_ds3_set_100ft,		/* set cable length */
+  lmc_ds3_set_scram,		/* set scrambler */
+  lmc_ds3_get_link_status,	/* get link status */
+  lmc_dummy_set_1,		/* set link status */
+  lmc_ds3_set_crc_length,	/* set CRC length */
+  lmc_dummy_set_1,		/* set T1 or E1 circuit type */
+  lmc_ds3_watchdog
+};
+
+lmc_media_t lmc_hssi_media = {
+  lmc_hssi_init,		/* special media init stuff */
+  lmc_hssi_default,		/* reset to default state */
+  lmc_hssi_set_status,		/* reset status to state provided */
+  lmc_hssi_set_clock,		/* set clock source */
+  lmc_dummy_set2_1,		/* set line speed */
+  lmc_dummy_set_1,		/* set cable length */
+  lmc_dummy_set_1,		/* set scrambler */
+  lmc_hssi_get_link_status,	/* get link status */
+  lmc_hssi_set_link_status,	/* set link status */
+  lmc_hssi_set_crc_length,	/* set CRC length */
+  lmc_dummy_set_1,		/* set T1 or E1 circuit type */
+  lmc_hssi_watchdog
+};
+
+lmc_media_t lmc_ssi_media = { lmc_ssi_init,	/* special media init stuff */
+  lmc_ssi_default,		/* reset to default state */
+  lmc_ssi_set_status,		/* reset status to state provided */
+  lmc_ssi_set_clock,		/* set clock source */
+  lmc_ssi_set_speed,		/* set line speed */
+  lmc_dummy_set_1,		/* set cable length */
+  lmc_dummy_set_1,		/* set scrambler */
+  lmc_ssi_get_link_status,	/* get link status */
+  lmc_ssi_set_link_status,	/* set link status */
+  lmc_ssi_set_crc_length,	/* set CRC length */
+  lmc_dummy_set_1,		/* set T1 or E1 circuit type */
+  lmc_ssi_watchdog
+};
+
+lmc_media_t lmc_t1_media = {
+  lmc_t1_init,			/* special media init stuff */
+  lmc_t1_default,		/* reset to default state */
+  lmc_t1_set_status,		/* reset status to state provided */
+  lmc_t1_set_clock,		/* set clock source */
+  lmc_dummy_set2_1,		/* set line speed */
+  lmc_dummy_set_1,		/* set cable length */
+  lmc_dummy_set_1,		/* set scrambler */
+  lmc_t1_get_link_status,	/* get link status */
+  lmc_dummy_set_1,		/* set link status */
+  lmc_t1_set_crc_length,	/* set CRC length */
+  lmc_t1_set_circuit_type,	/* set T1 or E1 circuit type */
+  lmc_t1_watchdog
+};
+
+
+#endif
+
diff --git a/drivers/net/wan/lmc/lmc_prot.h b/drivers/net/wan/lmc/lmc_prot.h
new file mode 100644
index 0000000..f3b1df9
--- /dev/null
+++ b/drivers/net/wan/lmc/lmc_prot.h
@@ -0,0 +1,15 @@
+#ifndef _LMC_PROTO_H_
+#define _LMC_PROTO_H_
+
+void lmc_proto_init(lmc_softc_t * const)
+void lmc_proto_attach(lmc_softc_t *sc const)
+void lmc_proto_detach(lmc_softc *sc const)
+void lmc_proto_reopen(lmc_softc_t *sc const)
+int lmc_proto_ioctl(lmc_softc_t *sc const, struct ifreq *ifr, int cmd)
+void lmc_proto_open(lmc_softc_t *sc const)
+void lmc_proto_close(lmc_softc_t *sc const)
+unsigned short lmc_proto_type(lmc_softc_t *sc const, struct skbuff *skb)
+
+
+#endif
+
diff --git a/drivers/net/wan/lmc/lmc_proto.c b/drivers/net/wan/lmc/lmc_proto.c
new file mode 100644
index 0000000..74876c0
--- /dev/null
+++ b/drivers/net/wan/lmc/lmc_proto.c
@@ -0,0 +1,249 @@
+ /*
+  * Copyright (c) 1997-2000 LAN Media Corporation (LMC)
+  * All rights reserved.  www.lanmedia.com
+  *
+  * This code is written by:
+  * Andrew Stanley-Jones (asj@cban.com)
+  * Rob Braun (bbraun@vix.com),
+  * Michael Graff (explorer@vix.com) and
+  * Matt Thomas (matt@3am-software.com).
+  *
+  * With Help By:
+  * David Boggs
+  * Ron Crane
+  * Allan Cox
+  *
+  * This software may be used and distributed according to the terms
+  * of the GNU General Public License version 2, incorporated herein by reference.
+  *
+  * Driver for the LanMedia LMC5200, LMC5245, LMC1000, LMC1200 cards.
+  */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/in.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/inet.h>
+#include <linux/workqueue.h>
+#include <linux/proc_fs.h>
+#include <linux/bitops.h>
+
+#include <net/syncppp.h>
+
+#include <asm/processor.h>             /* Processor type for cache alignment. */
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <linux/smp.h>
+
+#include "lmc.h"
+#include "lmc_var.h"
+#include "lmc_debug.h"
+#include "lmc_ioctl.h"
+#include "lmc_proto.h"
+
+/*
+ * The compile-time variable SPPPSTUP causes the module to be
+ * compiled without referencing any of the sync ppp routines.
+ */
+#ifdef SPPPSTUB
+#define SPPP_detach(d)	(void)0
+#define SPPP_open(d)	0
+#define SPPP_reopen(d)	(void)0
+#define SPPP_close(d)	(void)0
+#define SPPP_attach(d)	(void)0
+#define SPPP_do_ioctl(d,i,c)	-EOPNOTSUPP
+#else
+#define SPPP_attach(x)	sppp_attach((x)->pd)
+#define SPPP_detach(x)	sppp_detach((x)->pd->dev)
+#define SPPP_open(x)	sppp_open((x)->pd->dev)
+#define SPPP_reopen(x)	sppp_reopen((x)->pd->dev)
+#define SPPP_close(x)	sppp_close((x)->pd->dev)
+#define SPPP_do_ioctl(x, y, z)	sppp_do_ioctl((x)->pd->dev, (y), (z))
+#endif
+
+// init
+void lmc_proto_init(lmc_softc_t *sc) /*FOLD00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_proto_init in");
+    switch(sc->if_type){
+    case LMC_PPP:
+        sc->pd = kmalloc(sizeof(struct ppp_device), GFP_KERNEL);
+	if (!sc->pd) {
+		printk("lmc_proto_init(): kmalloc failure!\n");
+		return;
+	}
+        sc->pd->dev = sc->lmc_device;
+        sc->if_ptr = sc->pd;
+        break;
+    case LMC_RAW:
+        break;
+    default:
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_init out");
+}
+
+// attach
+void lmc_proto_attach(lmc_softc_t *sc) /*FOLD00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_proto_attach in");
+    switch(sc->if_type){
+    case LMC_PPP:
+        {
+            struct net_device *dev = sc->lmc_device;
+            SPPP_attach(sc);
+            dev->do_ioctl = lmc_ioctl;
+        }
+        break;
+    case LMC_NET:
+        {
+            struct net_device *dev = sc->lmc_device;
+            /*
+             * They set a few basics because they don't use sync_ppp
+             */
+            dev->flags |= IFF_POINTOPOINT;
+            dev->hard_header = NULL;
+            dev->hard_header_len = 0;
+            dev->addr_len = 0;
+        }
+    case LMC_RAW: /* Setup the task queue, maybe we should notify someone? */
+        {
+        }
+    default:
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_attach out");
+}
+
+// detach
+void lmc_proto_detach(lmc_softc_t *sc) /*FOLD00*/
+{
+    switch(sc->if_type){
+    case LMC_PPP:
+        SPPP_detach(sc);
+        break;
+    case LMC_RAW: /* Tell someone we're detaching? */
+        break;
+    default:
+        break;
+    }
+
+}
+
+// reopen
+void lmc_proto_reopen(lmc_softc_t *sc) /*FOLD00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_proto_reopen in");
+    switch(sc->if_type){
+    case LMC_PPP:
+        SPPP_reopen(sc);
+        break;
+    case LMC_RAW: /* Reset the interface after being down, prerape to receive packets again */
+        break;
+    default:
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_reopen out");
+}
+
+
+// ioctl
+int lmc_proto_ioctl(lmc_softc_t *sc, struct ifreq *ifr, int cmd) /*FOLD00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_proto_ioctl out");
+    switch(sc->if_type){
+    case LMC_PPP:
+        return SPPP_do_ioctl (sc, ifr, cmd);
+        break;
+    default:
+        return -EOPNOTSUPP;
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_ioctl out");
+}
+
+// open
+void lmc_proto_open(lmc_softc_t *sc) /*FOLD00*/
+{
+    int ret;
+
+    lmc_trace(sc->lmc_device, "lmc_proto_open in");
+    switch(sc->if_type){
+    case LMC_PPP:
+        ret = SPPP_open(sc);
+        if(ret < 0)
+            printk("%s: syncPPP open failed: %d\n", sc->name, ret);
+        break;
+    case LMC_RAW: /* We're about to start getting packets! */
+        break;
+    default:
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_open out");
+}
+
+// close
+
+void lmc_proto_close(lmc_softc_t *sc) /*FOLD00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_proto_close in");
+    switch(sc->if_type){
+    case LMC_PPP:
+        SPPP_close(sc);
+        break;
+    case LMC_RAW: /* Interface going down */
+        break;
+    default:
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_close out");
+}
+
+unsigned short lmc_proto_type(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_proto_type in");
+    switch(sc->if_type){
+    case LMC_PPP:
+        return htons(ETH_P_WAN_PPP);
+        break;
+    case LMC_NET:
+        return htons(ETH_P_802_2);
+        break;
+    case LMC_RAW: /* Packet type for skbuff kind of useless */
+        return htons(ETH_P_802_2);
+        break;
+    default:
+        printk(KERN_WARNING "%s: No protocol set for this interface, assuming 802.2 (which is wrong!!)\n", sc->name);
+        return htons(ETH_P_802_2);
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_tye out");
+
+}
+
+void lmc_proto_netif(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/
+{
+    lmc_trace(sc->lmc_device, "lmc_proto_netif in");
+    switch(sc->if_type){
+    case LMC_PPP:
+    case LMC_NET:
+    default:
+        skb->dev->last_rx = jiffies;
+        netif_rx(skb);
+        break;
+    case LMC_RAW:
+        break;
+    }
+    lmc_trace(sc->lmc_device, "lmc_proto_netif out");
+}
+
diff --git a/drivers/net/wan/lmc/lmc_proto.h b/drivers/net/wan/lmc/lmc_proto.h
new file mode 100644
index 0000000..080a557
--- /dev/null
+++ b/drivers/net/wan/lmc/lmc_proto.h
@@ -0,0 +1,16 @@
+#ifndef _LMC_PROTO_H_
+#define _LMC_PROTO_H_
+
+void lmc_proto_init(lmc_softc_t *sc);
+void lmc_proto_attach(lmc_softc_t *sc);
+void lmc_proto_detach(lmc_softc_t *sc);
+void lmc_proto_reopen(lmc_softc_t *sc);
+int lmc_proto_ioctl(lmc_softc_t *sc, struct ifreq *ifr, int cmd);
+void lmc_proto_open(lmc_softc_t *sc);
+void lmc_proto_close(lmc_softc_t *sc);
+unsigned short lmc_proto_type(lmc_softc_t *sc, struct sk_buff *skb);
+void lmc_proto_netif(lmc_softc_t *sc, struct sk_buff *skb);
+int lmc_skb_rawpackets(char *buf, char **start, off_t offset, int len, int unused);
+
+#endif
+
diff --git a/drivers/net/wan/lmc/lmc_var.h b/drivers/net/wan/lmc/lmc_var.h
new file mode 100644
index 0000000..6d003a3
--- /dev/null
+++ b/drivers/net/wan/lmc/lmc_var.h
@@ -0,0 +1,570 @@
+#ifndef _LMC_VAR_H_
+#define _LMC_VAR_H_
+
+/* $Id: lmc_var.h,v 1.17 2000/04/06 12:16:47 asj Exp $ */
+
+ /*
+  * Copyright (c) 1997-2000 LAN Media Corporation (LMC)
+  * All rights reserved.  www.lanmedia.com
+  *
+  * This code is written by:
+  * Andrew Stanley-Jones (asj@cban.com)
+  * Rob Braun (bbraun@vix.com),
+  * Michael Graff (explorer@vix.com) and
+  * Matt Thomas (matt@3am-software.com).
+  *
+  * This software may be used and distributed according to the terms
+  * of the GNU General Public License version 2, incorporated herein by reference.
+  */
+
+#include <linux/timer.h>
+
+#ifndef __KERNEL__
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#define BITS_PER_LONG 32 
+
+#endif
+
+/*
+ * basic definitions used in lmc include files
+ */
+
+typedef struct lmc___softc lmc_softc_t;
+typedef struct lmc___media lmc_media_t;
+typedef struct lmc___ctl lmc_ctl_t;
+
+#define lmc_csrptr_t    unsigned long
+#define u_int16_t	u16
+#define u_int8_t	u8
+#define tulip_uint32_t	u32
+
+#define LMC_REG_RANGE 0x80
+
+#define LMC_PRINTF_FMT  "%s"
+#define LMC_PRINTF_ARGS	(sc->lmc_device->name)
+
+#define TX_TIMEOUT (2*HZ)
+
+#define LMC_TXDESCS            32
+#define LMC_RXDESCS            32
+
+#define LMC_LINK_UP            1
+#define LMC_LINK_DOWN          0
+
+/* These macros for generic read and write to and from the dec chip */
+#define LMC_CSR_READ(sc, csr) \
+	inl((sc)->lmc_csrs.csr)
+#define LMC_CSR_WRITE(sc, reg, val) \
+	outl((val), (sc)->lmc_csrs.reg)
+
+//#ifdef _LINUX_DELAY_H
+//	#define SLOW_DOWN_IO udelay(2);
+//	#undef __SLOW_DOWN_IO
+//	#define __SLOW_DOWN_IO udelay(2);
+//#endif
+
+#define DELAY(n) SLOW_DOWN_IO
+
+#define lmc_delay() inl(sc->lmc_csrs.csr_9)
+
+/* This macro sync's up with the mii so that reads and writes can take place */
+#define LMC_MII_SYNC(sc) do {int n=32; while( n >= 0 ) { \
+                LMC_CSR_WRITE((sc), csr_9, 0x20000); \
+		lmc_delay(); \
+		LMC_CSR_WRITE((sc), csr_9, 0x30000); \
+                lmc_delay(); \
+		n--; }} while(0)
+
+struct lmc_regfile_t {
+    lmc_csrptr_t csr_busmode;                  /* CSR0 */
+    lmc_csrptr_t csr_txpoll;                   /* CSR1 */
+    lmc_csrptr_t csr_rxpoll;                   /* CSR2 */
+    lmc_csrptr_t csr_rxlist;                   /* CSR3 */
+    lmc_csrptr_t csr_txlist;                   /* CSR4 */
+    lmc_csrptr_t csr_status;                   /* CSR5 */
+    lmc_csrptr_t csr_command;                  /* CSR6 */
+    lmc_csrptr_t csr_intr;                     /* CSR7 */
+    lmc_csrptr_t csr_missed_frames;            /* CSR8 */
+    lmc_csrptr_t csr_9;                        /* CSR9 */
+    lmc_csrptr_t csr_10;                       /* CSR10 */
+    lmc_csrptr_t csr_11;                       /* CSR11 */
+    lmc_csrptr_t csr_12;                       /* CSR12 */
+    lmc_csrptr_t csr_13;                       /* CSR13 */
+    lmc_csrptr_t csr_14;                       /* CSR14 */
+    lmc_csrptr_t csr_15;                       /* CSR15 */
+};
+
+#define csr_enetrom             csr_9   /* 21040 */
+#define csr_reserved            csr_10  /* 21040 */
+#define csr_full_duplex         csr_11  /* 21040 */
+#define csr_bootrom             csr_10  /* 21041/21140A/?? */
+#define csr_gp                  csr_12  /* 21140* */
+#define csr_watchdog            csr_15  /* 21140* */
+#define csr_gp_timer            csr_11  /* 21041/21140* */
+#define csr_srom_mii            csr_9   /* 21041/21140* */
+#define csr_sia_status          csr_12  /* 2104x */
+#define csr_sia_connectivity    csr_13  /* 2104x */
+#define csr_sia_tx_rx           csr_14  /* 2104x */
+#define csr_sia_general         csr_15  /* 2104x */
+
+/* tulip length/control transmit descriptor definitions
+ *  used to define bits in the second tulip_desc_t field (length)
+ *  for the transmit descriptor -baz */
+
+#define LMC_TDES_FIRST_BUFFER_SIZE       ((u_int32_t)(0x000007FF))
+#define LMC_TDES_SECOND_BUFFER_SIZE      ((u_int32_t)(0x003FF800))
+#define LMC_TDES_HASH_FILTERING          ((u_int32_t)(0x00400000))
+#define LMC_TDES_DISABLE_PADDING         ((u_int32_t)(0x00800000))
+#define LMC_TDES_SECOND_ADDR_CHAINED     ((u_int32_t)(0x01000000))
+#define LMC_TDES_END_OF_RING             ((u_int32_t)(0x02000000))
+#define LMC_TDES_ADD_CRC_DISABLE         ((u_int32_t)(0x04000000))
+#define LMC_TDES_SETUP_PACKET            ((u_int32_t)(0x08000000))
+#define LMC_TDES_INVERSE_FILTERING       ((u_int32_t)(0x10000000))
+#define LMC_TDES_FIRST_SEGMENT           ((u_int32_t)(0x20000000))
+#define LMC_TDES_LAST_SEGMENT            ((u_int32_t)(0x40000000))
+#define LMC_TDES_INTERRUPT_ON_COMPLETION ((u_int32_t)(0x80000000))
+
+#define TDES_SECOND_BUFFER_SIZE_BIT_NUMBER  11
+#define TDES_COLLISION_COUNT_BIT_NUMBER     3
+
+/* Constants for the RCV descriptor RDES */
+
+#define LMC_RDES_OVERFLOW             ((u_int32_t)(0x00000001))
+#define LMC_RDES_CRC_ERROR            ((u_int32_t)(0x00000002))
+#define LMC_RDES_DRIBBLING_BIT            ((u_int32_t)(0x00000004))
+#define LMC_RDES_REPORT_ON_MII_ERR    ((u_int32_t)(0x00000008))
+#define LMC_RDES_RCV_WATCHDOG_TIMEOUT ((u_int32_t)(0x00000010))
+#define LMC_RDES_FRAME_TYPE           ((u_int32_t)(0x00000020))
+#define LMC_RDES_COLLISION_SEEN       ((u_int32_t)(0x00000040))
+#define LMC_RDES_FRAME_TOO_LONG       ((u_int32_t)(0x00000080))
+#define LMC_RDES_LAST_DESCRIPTOR      ((u_int32_t)(0x00000100))
+#define LMC_RDES_FIRST_DESCRIPTOR     ((u_int32_t)(0x00000200))
+#define LMC_RDES_MULTICAST_FRAME      ((u_int32_t)(0x00000400))
+#define LMC_RDES_RUNT_FRAME           ((u_int32_t)(0x00000800))
+#define LMC_RDES_DATA_TYPE            ((u_int32_t)(0x00003000))
+#define LMC_RDES_LENGTH_ERROR         ((u_int32_t)(0x00004000))
+#define LMC_RDES_ERROR_SUMMARY        ((u_int32_t)(0x00008000))
+#define LMC_RDES_FRAME_LENGTH         ((u_int32_t)(0x3FFF0000))
+#define LMC_RDES_OWN_BIT              ((u_int32_t)(0x80000000))
+
+#define RDES_FRAME_LENGTH_BIT_NUMBER       16
+
+#define LMC_RDES_ERROR_MASK ( (u_int32_t)( \
+	  LMC_RDES_OVERFLOW \
+	| LMC_RDES_DRIBBLING_BIT \
+	| LMC_RDES_REPORT_ON_MII_ERR \
+        | LMC_RDES_COLLISION_SEEN ) )
+
+
+/*
+ * Ioctl info
+ */
+
+typedef struct {
+	u_int32_t	n;
+	u_int32_t	m;
+	u_int32_t	v;
+	u_int32_t	x;
+	u_int32_t	r;
+	u_int32_t	f;
+	u_int32_t	exact;
+} lmc_av9110_t;
+
+/*
+ * Common structure passed to the ioctl code.
+ */
+struct lmc___ctl {
+	u_int32_t	cardtype;
+	u_int32_t	clock_source;		/* HSSI, T1 */
+	u_int32_t	clock_rate;		/* T1 */
+	u_int32_t	crc_length;
+	u_int32_t	cable_length;		/* DS3 */
+	u_int32_t	scrambler_onoff;	/* DS3 */
+	u_int32_t	cable_type;		/* T1 */
+	u_int32_t	keepalive_onoff;	/* protocol */
+	u_int32_t	ticks;			/* ticks/sec */
+	union {
+		lmc_av9110_t	ssi;
+	} cardspec;
+	u_int32_t       circuit_type;   /* T1 or E1 */
+};
+
+
+/*
+ * Carefull, look at the data sheet, there's more to this
+ * structure than meets the eye.  It should probably be:
+ *
+ * struct tulip_desc_t {
+ *         u8  own:1;
+ *         u32 status:31;
+ *         u32 control:10;
+ *         u32 buffer1;
+ *         u32 buffer2;
+ * };
+ * You could also expand status control to provide more bit information
+ */
+
+struct tulip_desc_t {
+	s32 status;
+	s32 length;
+	u32 buffer1;
+	u32 buffer2;
+};
+
+/*
+ * media independent methods to check on media status, link, light LEDs,
+ * etc.
+ */
+struct lmc___media {
+	void	(* init)(lmc_softc_t * const);
+	void	(* defaults)(lmc_softc_t * const);
+	void	(* set_status)(lmc_softc_t * const, lmc_ctl_t *);
+	void	(* set_clock_source)(lmc_softc_t * const, int);
+	void	(* set_speed)(lmc_softc_t * const, lmc_ctl_t *);
+	void	(* set_cable_length)(lmc_softc_t * const, int);
+	void	(* set_scrambler)(lmc_softc_t * const, int);
+	int	(* get_link_status)(lmc_softc_t * const);
+	void	(* set_link_status)(lmc_softc_t * const, int);
+	void	(* set_crc_length)(lmc_softc_t * const, int);
+        void    (* set_circuit_type)(lmc_softc_t * const, int);
+        void	(* watchdog)(lmc_softc_t * const);
+};
+
+
+#define STATCHECK     0xBEEFCAFE
+
+/*  Included in this structure are first
+ *   - standard net_device_stats
+ *   - some other counters used for debug and driver performance
+ *  evaluation -baz
+ */
+struct lmc_statistics
+{
+        unsigned long     rx_packets;             /* total packets received       */
+        unsigned long     tx_packets;             /* total packets transmitted    */
+	unsigned long     rx_bytes;
+        unsigned long     tx_bytes;
+        
+        unsigned long     rx_errors;              /* bad packets received         */
+        unsigned long     tx_errors;              /* packet transmit problems     */
+        unsigned long     rx_dropped;             /* no space in linux buffers    */
+        unsigned long     tx_dropped;             /* no space available in linux  */
+        unsigned long     multicast;              /* multicast packets received   */
+        unsigned long     collisions;
+
+        /* detailed rx_errors: */
+        unsigned long     rx_length_errors;
+        unsigned long     rx_over_errors;         /* receiver ring buff overflow  */
+        unsigned long     rx_crc_errors;          /* recved pkt with crc error    */
+        unsigned long     rx_frame_errors;        /* recv'd frame alignment error */
+        unsigned long     rx_fifo_errors;         /* recv'r fifo overrun          */
+        unsigned long     rx_missed_errors;       /* receiver missed packet       */
+
+        /* detailed tx_errors */
+        unsigned long     tx_aborted_errors;
+        unsigned long     tx_carrier_errors;
+        unsigned long     tx_fifo_errors;
+        unsigned long     tx_heartbeat_errors;
+        unsigned long     tx_window_errors;
+
+        /* for cslip etc */
+        unsigned long rx_compressed;
+        unsigned long tx_compressed;
+
+        /* -------------------------------------
+         * Custom stats & counters follow -baz */
+        u_int32_t       version_size;
+        u_int32_t       lmc_cardtype;
+
+        u_int32_t       tx_ProcTimeout;
+        u_int32_t       tx_IntTimeout;
+        u_int32_t       tx_NoCompleteCnt;
+        u_int32_t       tx_MaxXmtsB4Int;
+        u_int32_t       tx_TimeoutCnt;
+        u_int32_t       tx_OutOfSyncPtr;
+        u_int32_t       tx_tbusy0;
+        u_int32_t       tx_tbusy1;
+        u_int32_t       tx_tbusy_calls;
+        u_int32_t       resetCount;
+        u_int32_t       lmc_txfull;
+        u_int32_t       tbusy;
+        u_int32_t       dirtyTx;
+        u_int32_t       lmc_next_tx;
+        u_int32_t       otherTypeCnt;
+        u_int32_t       lastType;
+        u_int32_t       lastTypeOK;
+        u_int32_t       txLoopCnt;
+        u_int32_t       usedXmtDescripCnt;
+        u_int32_t       txIndexCnt;
+        u_int32_t       rxIntLoopCnt;
+
+        u_int32_t       rx_SmallPktCnt;
+        u_int32_t       rx_BadPktSurgeCnt;
+        u_int32_t       rx_BuffAllocErr;
+        u_int32_t       tx_lossOfClockCnt;
+
+        /* T1 error counters */
+        u_int32_t       framingBitErrorCount;
+        u_int32_t       lineCodeViolationCount;
+
+        u_int32_t       lossOfFrameCount;
+        u_int32_t       changeOfFrameAlignmentCount;
+        u_int32_t       severelyErroredFrameCount;
+
+        u_int32_t       check;
+};
+
+
+typedef struct lmc_xinfo {
+        u_int32_t       Magic0;                         /* BEEFCAFE */
+
+        u_int32_t       PciCardType;
+        u_int32_t       PciSlotNumber;          /* PCI slot number       */
+
+        u_int16_t       DriverMajorVersion;
+        u_int16_t       DriverMinorVersion;
+        u_int16_t       DriverSubVersion;
+
+        u_int16_t       XilinxRevisionNumber;
+        u_int16_t       MaxFrameSize;
+
+        u_int16_t       t1_alarm1_status;
+        u_int16_t       t1_alarm2_status;
+
+        int                     link_status;
+        u_int32_t       mii_reg16;
+
+        u_int32_t       Magic1;                         /* DEADBEEF */
+} LMC_XINFO;
+
+
+/*
+ * forward decl
+ */
+struct lmc___softc {
+        void *if_ptr;   /* General purpose pointer (used by SPPP) */
+	char                   *name;
+	u8			board_idx;
+	struct lmc_statistics   stats;
+	struct net_device          *lmc_device;
+
+	int                     hang, rxdesc, bad_packet, some_counter;
+	u_int32_t               txgo;
+	struct lmc_regfile_t	lmc_csrs;
+	volatile u_int32_t	lmc_txtick;
+	volatile u_int32_t	lmc_rxtick;
+	u_int32_t		lmc_flags;
+	u_int32_t		lmc_intrmask;	/* our copy of csr_intr */
+	u_int32_t		lmc_cmdmode;	/* our copy of csr_cmdmode */
+	u_int32_t		lmc_busmode;	/* our copy of csr_busmode */
+	u_int32_t		lmc_gpio_io;	/* state of in/out settings */
+	u_int32_t		lmc_gpio;	/* state of outputs */
+	struct sk_buff*		lmc_txq[LMC_TXDESCS];
+	struct sk_buff*		lmc_rxq[LMC_RXDESCS];
+	volatile
+	struct tulip_desc_t	lmc_rxring[LMC_RXDESCS];
+	volatile
+	struct tulip_desc_t	lmc_txring[LMC_TXDESCS];
+	unsigned int		lmc_next_rx, lmc_next_tx;
+	volatile
+	unsigned int		lmc_taint_tx, lmc_taint_rx;
+	int			lmc_tx_start, lmc_txfull;
+	int			lmc_txbusy;
+	u_int16_t		lmc_miireg16;
+	int			lmc_ok;
+	int			last_link_status;
+	int			lmc_cardtype;
+	u_int32_t               last_frameerr;
+	lmc_media_t	       *lmc_media;
+	struct timer_list	timer;
+	lmc_ctl_t		ictl;
+	u_int32_t		TxDescriptControlInit;  
+
+	int                     tx_TimeoutInd; /* additional driver state */
+	int                     tx_TimeoutDisplay;
+	unsigned int		lastlmc_taint_tx;
+	int                     lasttx_packets;
+	u_int32_t		tx_clockState;
+	u_int32_t		lmc_crcSize;
+	LMC_XINFO		lmc_xinfo; 
+	char                    lmc_yel, lmc_blue, lmc_red; /* for T1 and DS3 */
+        char                    lmc_timing; /* for HSSI and SSI */
+        int                     got_irq;
+
+        char                    last_led_err[4];
+
+        u32                     last_int;
+        u32                     num_int;
+
+	spinlock_t              lmc_lock;
+        u_int16_t               if_type;       /* PPP or NET */
+        struct ppp_device       *pd;
+
+        /* Failure cases */
+        u8                       failed_ring;
+        u8                       failed_recv_alloc;
+
+        /* Structure check */
+        u32                     check;
+};
+
+#define LMC_PCI_TIME 1
+#define LMC_EXT_TIME 0
+
+#define PKT_BUF_SZ              1542  /* was 1536 */
+
+/* CSR5 settings */
+#define TIMER_INT     0x00000800
+#define TP_LINK_FAIL  0x00001000
+#define TP_LINK_PASS  0x00000010
+#define NORMAL_INT    0x00010000
+#define ABNORMAL_INT  0x00008000
+#define RX_JABBER_INT 0x00000200
+#define RX_DIED       0x00000100
+#define RX_NOBUFF     0x00000080
+#define RX_INT        0x00000040
+#define TX_FIFO_UNDER 0x00000020
+#define TX_JABBER     0x00000008
+#define TX_NOBUFF     0x00000004
+#define TX_DIED       0x00000002
+#define TX_INT        0x00000001
+
+/* CSR6 settings */
+#define OPERATION_MODE  0x00000200 /* Full Duplex      */
+#define PROMISC_MODE    0x00000040 /* Promiscuous Mode */
+#define RECIEVE_ALL     0x40000000 /* Recieve All      */
+#define PASS_BAD_FRAMES 0x00000008 /* Pass Bad Frames  */
+
+/* Dec control registers  CSR6 as well */
+#define LMC_DEC_ST 0x00002000
+#define LMC_DEC_SR 0x00000002
+
+/* CSR15 settings */
+#define RECV_WATCHDOG_DISABLE 0x00000010
+#define JABBER_DISABLE        0x00000001
+
+/* More settings */
+/*
+ * aSR6 -- Command (Operation Mode) Register
+ */
+#define TULIP_CMD_RECEIVEALL    0x40000000L /* (RW)  Receivel all frames? */
+#define TULIP_CMD_MUSTBEONE     0x02000000L /* (RW)  Must Be One (21140) */
+#define TULIP_CMD_TXTHRSHLDCTL  0x00400000L /* (RW)  Transmit Threshold Mode (21140) */
+#define TULIP_CMD_STOREFWD      0x00200000L /* (RW)  Store and Foward (21140) */
+#define TULIP_CMD_NOHEARTBEAT   0x00080000L /* (RW)  No Heartbeat (21140) */
+#define TULIP_CMD_PORTSELECT    0x00040000L /* (RW)  Post Select (100Mb) (21140) */
+#define TULIP_CMD_FULLDUPLEX    0x00000200L /* (RW)  Full Duplex Mode */
+#define TULIP_CMD_OPERMODE      0x00000C00L /* (RW)  Operating Mode */
+#define TULIP_CMD_PROMISCUOUS   0x00000041L /* (RW)  Promiscuous Mode */
+#define TULIP_CMD_PASSBADPKT    0x00000008L /* (RW)  Pass Bad Frames */
+#define TULIP_CMD_THRESHOLDCTL  0x0000C000L /* (RW)  Threshold Control */
+
+#define TULIP_GP_PINSET         0x00000100L
+#define TULIP_BUSMODE_SWRESET   0x00000001L
+#define TULIP_WATCHDOG_TXDISABLE 0x00000001L
+#define TULIP_WATCHDOG_RXDISABLE 0x00000010L
+
+#define TULIP_STS_NORMALINTR    0x00010000L /* (RW)  Normal Interrupt */
+#define TULIP_STS_ABNRMLINTR    0x00008000L /* (RW)  Abnormal Interrupt */
+#define TULIP_STS_ERI           0x00004000L /* (RW)  Early Receive Interrupt */
+#define TULIP_STS_SYSERROR      0x00002000L /* (RW)  System Error */
+#define TULIP_STS_GTE           0x00000800L /* (RW)  General Pupose Timer Exp */
+#define TULIP_STS_ETI           0x00000400L /* (RW)  Early Transmit Interrupt */
+#define TULIP_STS_RXWT          0x00000200L /* (RW)  Receiver Watchdog Timeout */
+#define TULIP_STS_RXSTOPPED     0x00000100L /* (RW)  Receiver Process Stopped */
+#define TULIP_STS_RXNOBUF       0x00000080L /* (RW)  Receive Buf Unavail */
+#define TULIP_STS_RXINTR        0x00000040L /* (RW)  Receive Interrupt */
+#define TULIP_STS_TXUNDERFLOW   0x00000020L /* (RW)  Transmit Underflow */
+#define TULIP_STS_TXJABER       0x00000008L /* (RW)  Jabber timeout */
+#define TULIP_STS_TXNOBUF       0x00000004L
+#define TULIP_STS_TXSTOPPED     0x00000002L /* (RW)  Transmit Process Stopped */
+#define TULIP_STS_TXINTR        0x00000001L /* (RW)  Transmit Interrupt */
+
+#define TULIP_STS_RXS_STOPPED   0x00000000L /*        000 - Stopped */
+
+#define TULIP_STS_RXSTOPPED     0x00000100L             /* (RW)  Receive Process Stopped */
+#define TULIP_STS_RXNOBUF       0x00000080L
+
+#define TULIP_CMD_TXRUN         0x00002000L /* (RW)  Start/Stop Transmitter */
+#define TULIP_CMD_RXRUN         0x00000002L /* (RW)  Start/Stop Receive Filtering */
+#define TULIP_DSTS_TxDEFERRED   0x00000001      /* Initially Deferred */
+#define TULIP_DSTS_OWNER        0x80000000      /* Owner (1 = 21040) */
+#define TULIP_DSTS_RxMIIERR     0x00000008
+#define LMC_DSTS_ERRSUM         (TULIP_DSTS_RxMIIERR)
+
+#define TULIP_DEFAULT_INTR_MASK  (TULIP_STS_NORMALINTR \
+  | TULIP_STS_RXINTR       \
+  | TULIP_STS_TXINTR     \
+  | TULIP_STS_ABNRMLINTR \
+  | TULIP_STS_SYSERROR   \
+  | TULIP_STS_TXSTOPPED  \
+  | TULIP_STS_TXUNDERFLOW\
+  | TULIP_STS_RXSTOPPED )
+
+#define DESC_OWNED_BY_SYSTEM   ((u_int32_t)(0x00000000))
+#define DESC_OWNED_BY_DC21X4   ((u_int32_t)(0x80000000))
+
+#ifndef TULIP_CMD_RECEIVEALL
+#define TULIP_CMD_RECEIVEALL 0x40000000L
+#endif
+
+/* Adapter module number */
+#define LMC_ADAP_HSSI           2
+#define LMC_ADAP_DS3            3
+#define LMC_ADAP_SSI            4
+#define LMC_ADAP_T1             5
+
+#define HDLC_HDR_LEN  4
+#define HDLC_ADDR_LEN 1
+#define HDLC_SLARP    0x8035
+#define LMC_MTU 1500
+#define SLARP_LINECHECK 2
+
+#define LMC_CRC_LEN_16 2  /* 16-bit CRC */
+#define LMC_CRC_LEN_32 4
+
+#ifdef LMC_HDLC
+/* definition of an hdlc header. */
+struct hdlc_hdr
+{
+	u8  address;
+	u8  control;
+	u16 type;
+};
+
+/* definition of a slarp header. */
+struct slarp
+{
+	long code;
+	union sl
+	{
+		struct
+		{
+			ulong address;
+			ulong mask;
+			ushort unused;
+		} add;
+		struct
+		{
+			ulong mysequence;
+			ulong yoursequence;
+			ushort reliability;
+			ulong time;
+		} chk;
+	} t;
+};
+#endif /* LMC_HDLC */
+
+
+#endif /* _LMC_VAR_H_ */