staging: Add driver to support wanPMC-CxT1E1 card.
authorBob Beers <bob.beers@gmail.com>
Thu, 4 Mar 2010 13:40:46 +0000 (08:40 -0500)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 11 May 2010 18:35:31 +0000 (11:35 -0700)
Obviously still needs serious attention, but it compiles.

Original author: Rick Dobbs

Add driver to support wanPMC-CxT1E1 card.

This card provides 1-4 ports of T1E1 in PMC form factor.

Note, Rick doesn't want his email showing up as the "From:" author, but
has given his blessing to have the code included in the kernel tree.

Signed-off-by: Bob Beers <bob.beers@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
32 files changed:
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/cxt1e1/Kconfig [new file with mode: 0644]
drivers/staging/cxt1e1/Makefile [new file with mode: 0644]
drivers/staging/cxt1e1/comet.c [new file with mode: 0644]
drivers/staging/cxt1e1/comet.h [new file with mode: 0644]
drivers/staging/cxt1e1/comet_tables.c [new file with mode: 0644]
drivers/staging/cxt1e1/comet_tables.h [new file with mode: 0644]
drivers/staging/cxt1e1/functions.c [new file with mode: 0644]
drivers/staging/cxt1e1/hwprobe.c [new file with mode: 0644]
drivers/staging/cxt1e1/libsbew.h [new file with mode: 0644]
drivers/staging/cxt1e1/linux.c [new file with mode: 0644]
drivers/staging/cxt1e1/musycc.c [new file with mode: 0644]
drivers/staging/cxt1e1/musycc.h [new file with mode: 0644]
drivers/staging/cxt1e1/ossiRelease.c [new file with mode: 0644]
drivers/staging/cxt1e1/pmc93x6_eeprom.c [new file with mode: 0644]
drivers/staging/cxt1e1/pmc93x6_eeprom.h [new file with mode: 0644]
drivers/staging/cxt1e1/pmcc4.h [new file with mode: 0644]
drivers/staging/cxt1e1/pmcc4_cpld.h [new file with mode: 0644]
drivers/staging/cxt1e1/pmcc4_defs.h [new file with mode: 0644]
drivers/staging/cxt1e1/pmcc4_drv.c [new file with mode: 0644]
drivers/staging/cxt1e1/pmcc4_ioctls.h [new file with mode: 0644]
drivers/staging/cxt1e1/pmcc4_private.h [new file with mode: 0644]
drivers/staging/cxt1e1/pmcc4_sysdep.h [new file with mode: 0644]
drivers/staging/cxt1e1/sbe_bid.h [new file with mode: 0644]
drivers/staging/cxt1e1/sbe_promformat.h [new file with mode: 0644]
drivers/staging/cxt1e1/sbecom_inline_linux.h [new file with mode: 0644]
drivers/staging/cxt1e1/sbecrc.c [new file with mode: 0644]
drivers/staging/cxt1e1/sbeid.c [new file with mode: 0644]
drivers/staging/cxt1e1/sbeproc.c [new file with mode: 0644]
drivers/staging/cxt1e1/sbeproc.h [new file with mode: 0644]
drivers/staging/cxt1e1/sbew_ioc.h [new file with mode: 0644]

index 7696a664f8a554dd60c720e15054bf4188b64bfb..8db8632541f1def95e34a2bb94b23f985ca6f0da 100644 (file)
@@ -139,5 +139,7 @@ source "drivers/staging/dt3155/Kconfig"
 
 source "drivers/staging/crystalhd/Kconfig"
 
+source "drivers/staging/cxt1e1/Kconfig"
+
 endif # !STAGING_EXCLUDE_BUILD
 endif # STAGING
index ea2e70e2fed466f49a082164c0177ba054b8af98..ab61e2601ffd0b7136f88410d0b278197ec4d750 100644 (file)
@@ -51,3 +51,4 @@ obj-$(CONFIG_PCMCIA_NETWAVE)  += netwave/
 obj-$(CONFIG_FB_SM7XX)         += sm7xx/
 obj-$(CONFIG_DT3155)           += dt3155/
 obj-$(CONFIG_CRYSTALHD)                += crystalhd/
+obj-$(CONFIG_CXT1E1)           += cxt1e1/
diff --git a/drivers/staging/cxt1e1/Kconfig b/drivers/staging/cxt1e1/Kconfig
new file mode 100644 (file)
index 0000000..68e9b6d
--- /dev/null
@@ -0,0 +1,22 @@
+config CXT1E1
+       tristate "SBE wanPMC-C[421]E1T1 hardware support"
+       depends on HDLC && PCI
+       ---help---
+      This driver supports the SBE wanPMC-CxT1E1 1, 2 and 4 port T3
+      channelized stream WAN adapter card which contains a HDLC/Transparent
+      mode controller.
+
+      If you want to compile this driver as a module
+      say M here and read <file:Documentation/modules.txt>.
+      The module will be called 'cxt1e1'.
+
+      If unsure, say N.
+
+config SBE_PMCC4_NCOMM
+       bool "SBE PMCC4 NCOMM support"
+       depends on CXT1E1
+       ---help---
+      SBE supplies optional support for NCOMM products.
+
+      If you have purchased this optional support you must say Y or M
+      here to allow the driver to operate with the NCOMM product.
diff --git a/drivers/staging/cxt1e1/Makefile b/drivers/staging/cxt1e1/Makefile
new file mode 100644 (file)
index 0000000..10020d7
--- /dev/null
@@ -0,0 +1,19 @@
+obj-$(CONFIG_CXT1E1)   += cxt1e1.o
+
+EXTRA_CFLAGS += -DSBE_PMCC4_ENABLE
+EXTRA_CFLAGS += -DSBE_ISR_TASKLET
+EXTRA_CFLAGS += -DSBE_INCLUDE_SYMBOLS
+
+cxt1e1-objs +=         \
+  ossiRelease.o        \
+  musycc.o             \
+  pmcc4_drv.o          \
+  comet.o              \
+  linux.o              \
+  functions.o          \
+  hwprobe.o            \
+  sbeproc.o            \
+  pmc93x6_eeprom.o     \
+  sbecrc.o             \
+  comet_tables.o       \
+  sbeid.o
diff --git a/drivers/staging/cxt1e1/comet.c b/drivers/staging/cxt1e1/comet.c
new file mode 100644 (file)
index 0000000..b709099
--- /dev/null
@@ -0,0 +1,566 @@
+/* Copyright (C) 2003-2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include <asm/io.h>
+#include <linux/hdlc.h>
+#include "pmcc4_sysdep.h"
+#include "sbecom_inline_linux.h"
+#include "libsbew.h"
+#include "pmcc4.h"
+#include "comet.h"
+#include "comet_tables.h"
+
+#ifdef SBE_INCLUDE_SYMBOLS
+#define STATIC
+#else
+#define STATIC  static
+#endif
+
+
+extern int  log_level;
+
+#define COMET_NUM_SAMPLES   24  /* Number of entries in the waveform table */
+#define COMET_NUM_UNITS     5   /* Number of points per entry in table */
+
+/* forward references */
+STATIC void SetPwrLevel (comet_t * comet);
+STATIC void WrtRcvEqualizerTbl (ci_t * ci, comet_t * comet, u_int32_t *table);
+STATIC void WrtXmtWaveformTbl (ci_t * ci, comet_t * comet, u_int8_t table[COMET_NUM_SAMPLES][COMET_NUM_UNITS]);
+
+
+void       *TWV_table[12] = {
+    TWVLongHaul0DB, TWVLongHaul7_5DB, TWVLongHaul15DB, TWVLongHaul22_5DB,
+    TWVShortHaul0, TWVShortHaul1, TWVShortHaul2, TWVShortHaul3, TWVShortHaul4,
+    TWVShortHaul5,
+    TWV_E1_75Ohm,    /** PORT POINT - 75 Ohm not supported **/
+    TWV_E1_120Ohm
+};
+
+
+static int
+lbo_tbl_lkup (int t1, int lbo)
+{
+    if ((lbo < CFG_LBO_LH0) || (lbo > CFG_LBO_E120))    /* error switches to
+                                                         * default */
+    {
+        if (t1)
+            lbo = CFG_LBO_LH0;  /* default T1 waveform table */
+        else
+            lbo = CFG_LBO_E120;     /* default E1 waveform table */
+    }
+    return (lbo - 1);               /* make index ZERO relative */
+}
+
+
+void
+init_comet (void *ci, comet_t * comet, u_int32_t port_mode, int clockmaster,
+            u_int8_t moreParams)
+{
+    u_int8_t isT1mode;
+    u_int8_t    tix = CFG_LBO_LH0;      /* T1 default */
+
+    isT1mode = IS_FRAME_ANY_T1 (port_mode);
+    /* T1 or E1 */
+    if (isT1mode)
+    {
+        pci_write_32 ((u_int32_t *) &comet->gbl_cfg, 0xa0);     /* Select T1 Mode & PIO
+                                                                 * output enabled */
+        tix = lbo_tbl_lkup (isT1mode, CFG_LBO_LH0);     /* default T1 waveform
+                                                         * table */
+    } else
+    {
+        pci_write_32 ((u_int32_t *) &comet->gbl_cfg, 0x81);     /* Select E1 Mode & PIO
+                                                                 * output enabled */
+        tix = lbo_tbl_lkup (isT1mode, CFG_LBO_E120);    /* default E1 waveform
+                                                         * table */
+    }
+
+    if (moreParams & CFG_LBO_MASK)
+        tix = lbo_tbl_lkup (isT1mode, moreParams & CFG_LBO_MASK);       /* dial-in requested
+                                                                         * waveform table */
+
+    /* Tx line Intfc cfg     ** Set for analog & no special patterns */
+    pci_write_32 ((u_int32_t *) &comet->tx_line_cfg, 0x00);     /* Transmit Line
+                                                                 * Interface Config. */
+
+    /* master test    ** Ignore Test settings for now */
+    pci_write_32 ((u_int32_t *) &comet->mtest, 0x00);   /* making sure it's
+                                                         * Default value */
+
+    /* Turn on Center (CENT) and everything else off */
+    pci_write_32 ((u_int32_t *) &comet->rjat_cfg, 0x10);        /* RJAT cfg */
+    /* Set Jitter Attenuation to recommend T1 values */
+    if (isT1mode)
+    {
+        pci_write_32 ((u_int32_t *) &comet->rjat_n1clk, 0x2F);  /* RJAT Divider N1
+                                                                 * Control */
+        pci_write_32 ((u_int32_t *) &comet->rjat_n2clk, 0x2F);  /* RJAT Divider N2
+                                                                 * Control */
+    } else
+    {
+        pci_write_32 ((u_int32_t *) &comet->rjat_n1clk, 0xFF);  /* RJAT Divider N1
+                                                                 * Control */
+        pci_write_32 ((u_int32_t *) &comet->rjat_n2clk, 0xFF);  /* RJAT Divider N2
+                                                                 * Control */
+    }
+
+    /* Turn on Center (CENT) and everything else off */
+    pci_write_32 ((u_int32_t *) &comet->tjat_cfg, 0x10);        /* TJAT Config. */
+
+    /* Do not bypass jitter attenuation and bypass elastic store */
+    pci_write_32 ((u_int32_t *) &comet->rx_opt, 0x00);  /* rx opts */
+
+    /* TJAT ctrl & TJAT divider ctrl */
+    /* Set Jitter Attenuation to recommended T1 values */
+    if (isT1mode)
+    {
+        pci_write_32 ((u_int32_t *) &comet->tjat_n1clk, 0x2F);  /* TJAT Divider N1
+                                                                 * Control */
+        pci_write_32 ((u_int32_t *) &comet->tjat_n2clk, 0x2F);  /* TJAT Divider N2
+                                                                 * Control */
+    } else
+    {
+        pci_write_32 ((u_int32_t *) &comet->tjat_n1clk, 0xFF);  /* TJAT Divider N1
+                                                                 * Control */
+        pci_write_32 ((u_int32_t *) &comet->tjat_n2clk, 0xFF);  /* TJAT Divider N2
+                                                                 * Control */
+    }
+
+    /* 1c: rx ELST cfg   20: tx ELST cfg  28&38: rx&tx data link ctrl */
+    if (isT1mode)
+    {                               /* Select 193-bit frame format */
+        pci_write_32 ((u_int32_t *) &comet->rx_elst_cfg, 0x00);
+        pci_write_32 ((u_int32_t *) &comet->tx_elst_cfg, 0x00);
+    } else
+    {                               /* Select 256-bit frame format */
+        pci_write_32 ((u_int32_t *) &comet->rx_elst_cfg, 0x03);
+        pci_write_32 ((u_int32_t *) &comet->tx_elst_cfg, 0x03);
+        pci_write_32 ((u_int32_t *) &comet->rxce1_ctl, 0x00);   /* disable T1 data link
+                                                                 * receive */
+        pci_write_32 ((u_int32_t *) &comet->txci1_ctl, 0x00);   /* disable T1 data link
+                                                                 * transmit */
+    }
+
+    /* the following is a default value */
+    /* Enable 8 out of 10 validation */
+    pci_write_32 ((u_int32_t *) &comet->t1_rboc_ena, 0x00);     /* t1RBOC
+                                                                 * enable(BOC:BitOriented
+                                                                 * Code) */
+    if (isT1mode)
+    {
+
+        /* IBCD cfg: aka Inband Code Detection ** loopback code length set to */
+        pci_write_32 ((u_int32_t *) &comet->ibcd_cfg, 0x04);    /* 6 bit down, 5 bit up
+                                                                 * (assert)  */
+        pci_write_32 ((u_int32_t *) &comet->ibcd_act, 0x08);    /* line loopback
+                                                                 * activate pattern */
+        pci_write_32 ((u_int32_t *) &comet->ibcd_deact, 0x24);  /* deactivate code
+                                                                 * pattern (i.e.001) */
+    }
+    /* 10: CDRC cfg 28&38: rx&tx data link 1 ctrl 48: t1 frmr cfg  */
+    /* 50: SIGX cfg, COSS (change of signaling state) 54: XBAS cfg  */
+    /* 60: t1 ALMI cfg */
+    /* Configure Line Coding */
+
+    switch (port_mode)
+    {
+    case CFG_FRAME_SF:              /* 1 - T1 B8ZS */
+        pci_write_32 ((u_int32_t *) &comet->cdrc_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->t1_frmr_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->sigx_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->t1_xbas_cfg, 0x20); /* 5:B8ZS */
+        pci_write_32 ((u_int32_t *) &comet->t1_almi_cfg, 0);
+        break;
+    case CFG_FRAME_ESF:     /* 2 - T1 B8ZS */
+        pci_write_32 ((u_int32_t *) &comet->cdrc_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->rxce1_ctl, 0x20);   /* Bit 5: T1 DataLink
+                                                                 * Enable */
+        pci_write_32 ((u_int32_t *) &comet->txci1_ctl, 0x20);   /* 5: T1 DataLink Enable */
+        pci_write_32 ((u_int32_t *) &comet->t1_frmr_cfg, 0x30); /* 4:ESF  5:ESFFA */
+        pci_write_32 ((u_int32_t *) &comet->sigx_cfg, 0x04);    /* 2:ESF */
+        pci_write_32 ((u_int32_t *) &comet->t1_xbas_cfg, 0x30); /* 4:ESF  5:B8ZS */
+        pci_write_32 ((u_int32_t *) &comet->t1_almi_cfg, 0x10); /* 4:ESF */
+        break;
+    case CFG_FRAME_E1PLAIN:         /* 3 - HDB3 */
+        pci_write_32 ((u_int32_t *) &comet->cdrc_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->sigx_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->e1_tran_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->e1_frmr_aopts, 0x40);
+        break;
+    case CFG_FRAME_E1CAS:           /* 4 - HDB3 */
+        pci_write_32 ((u_int32_t *) &comet->cdrc_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->sigx_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->e1_tran_cfg, 0x60);
+        pci_write_32 ((u_int32_t *) &comet->e1_frmr_aopts, 0);
+        break;
+    case CFG_FRAME_E1CRC:           /* 5 - HDB3 */
+        pci_write_32 ((u_int32_t *) &comet->cdrc_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->sigx_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->e1_tran_cfg, 0x10);
+        pci_write_32 ((u_int32_t *) &comet->e1_frmr_aopts, 0xc2);
+        break;
+    case CFG_FRAME_E1CRC_CAS:       /* 6 - HDB3 */
+        pci_write_32 ((u_int32_t *) &comet->cdrc_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->sigx_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->e1_tran_cfg, 0x70);
+        pci_write_32 ((u_int32_t *) &comet->e1_frmr_aopts, 0x82);
+        break;
+    case CFG_FRAME_SF_AMI:          /* 7 - T1 AMI */
+        pci_write_32 ((u_int32_t *) &comet->cdrc_cfg, 0x80);    /* Enable AMI Line
+                                                                 * Decoding */
+        pci_write_32 ((u_int32_t *) &comet->t1_frmr_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->t1_xbas_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->t1_almi_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->sigx_cfg, 0);
+        break;
+    case CFG_FRAME_ESF_AMI:         /* 8 - T1 AMI */
+        pci_write_32 ((u_int32_t *) &comet->cdrc_cfg, 0x80);    /* Enable AMI Line
+                                                                 * Decoding */
+        pci_write_32 ((u_int32_t *) &comet->rxce1_ctl, 0x20);   /* 5: T1 DataLink Enable */
+        pci_write_32 ((u_int32_t *) &comet->txci1_ctl, 0x20);   /* 5: T1 DataLink Enable */
+        pci_write_32 ((u_int32_t *) &comet->t1_frmr_cfg, 0x30); /* Bit 4:ESF  5:ESFFA */
+        pci_write_32 ((u_int32_t *) &comet->sigx_cfg, 0x04);    /* 2:ESF */
+        pci_write_32 ((u_int32_t *) &comet->t1_xbas_cfg, 0x10); /* 4:ESF */
+        pci_write_32 ((u_int32_t *) &comet->t1_almi_cfg, 0x10); /* 4:ESF */
+        break;
+    case CFG_FRAME_E1PLAIN_AMI:       /* 9 - AMI */
+        pci_write_32 ((u_int32_t *) &comet->cdrc_cfg, 0x80);    /* Enable AMI Line
+                                                                 * Decoding */
+        pci_write_32 ((u_int32_t *) &comet->sigx_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->e1_tran_cfg, 0x80);
+        pci_write_32 ((u_int32_t *) &comet->e1_frmr_aopts, 0x40);
+        break;
+    case CFG_FRAME_E1CAS_AMI:       /* 10 - AMI */
+        pci_write_32 ((u_int32_t *) &comet->cdrc_cfg, 0x80);    /* Enable AMI Line
+                                                                 * Decoding */
+        pci_write_32 ((u_int32_t *) &comet->sigx_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->e1_tran_cfg, 0xe0);
+        pci_write_32 ((u_int32_t *) &comet->e1_frmr_aopts, 0);
+        break;
+    case CFG_FRAME_E1CRC_AMI:       /* 11 - AMI */
+        pci_write_32 ((u_int32_t *) &comet->cdrc_cfg, 0x80);    /* Enable AMI Line
+                                                                 * Decoding */
+        pci_write_32 ((u_int32_t *) &comet->sigx_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->e1_tran_cfg, 0x90);
+        pci_write_32 ((u_int32_t *) &comet->e1_frmr_aopts, 0xc2);
+        break;
+    case CFG_FRAME_E1CRC_CAS_AMI:   /* 12 - AMI */
+        pci_write_32 ((u_int32_t *) &comet->cdrc_cfg, 0x80);    /* Enable AMI Line
+                                                                 * Decoding */
+        pci_write_32 ((u_int32_t *) &comet->sigx_cfg, 0);
+        pci_write_32 ((u_int32_t *) &comet->e1_tran_cfg, 0xf0);
+        pci_write_32 ((u_int32_t *) &comet->e1_frmr_aopts, 0x82);
+        break;
+    }                               /* end switch */
+
+    /***
+     * Set Full Frame mode (NXDSO[1] = 0, NXDSO[0] = 0)
+     * CMODE=1: Clock slave mode with BRCLK as an input,
+     * DE=0: Use falling edge of BRCLK for data,
+     * FE=0: Use falling edge of BRCLK for frame,
+     * CMS=0: Use backplane freq,
+     * RATE[1:0]=0,0: T1
+     ***/
+
+
+    /* 0x30: "BRIF cfg"; 0x20 is 'CMODE', 0x03 is (bit) rate */
+    /* note "rate bits can only be set once after reset" */
+    if (clockmaster)
+    {                               /* CMODE == clockMode, 0=clock master (so
+                                     * all 3 others should be slave) */
+        if (isT1mode)               /* rate = 1.544 Mb/s */
+            pci_write_32 ((u_int32_t *) &comet->brif_cfg, 0x00);        /* Comet 0 Master
+                                                                         * Mode(CMODE=0) */
+        else                        /* rate = 2.048 Mb/s */
+            pci_write_32 ((u_int32_t *) &comet->brif_cfg, 0x01);        /* Comet 0 Master
+                                                                         * Mode(CMODE=0) */
+
+        /* 31: BRIF frame pulse cfg  06: tx timing options */
+        pci_write_32 ((u_int32_t *) &comet->brif_fpcfg, 0x00);  /* Master Mode
+                                                                 * i.e.FPMODE=0 (@0x20) */
+        if ((moreParams & CFG_CLK_PORT_MASK) == CFG_CLK_PORT_INTERNAL)
+        {
+            if (log_level >= LOG_SBEBUG12)
+                printk (">> init_comet: clockmaster internal clock\n");
+            pci_write_32 ((u_int32_t *) &comet->tx_time, 0x0d); /* internal oscillator */
+        } else                      /* external clock source */
+        {
+            if (log_level >= LOG_SBEBUG12)
+                printk (">> init_comet: clockmaster external clock\n");
+            pci_write_32 ((u_int32_t *) &comet->tx_time, 0x09); /* loop timing
+                                                                 * (external) */
+        }
+
+    } else                          /* slave */
+    {
+        if (isT1mode)
+            pci_write_32 ((u_int32_t *) &comet->brif_cfg, 0x20);        /* Slave Mode(CMODE=1,
+                                                                         * see above) */
+        else
+            pci_write_32 ((u_int32_t *) &comet->brif_cfg, 0x21);        /* Slave Mode (CMODE=1) */
+        pci_write_32 ((u_int32_t *) &comet->brif_fpcfg, 0x20);  /* Slave Mode i.e.
+                                                                 * FPMODE=1 (@0x20) */
+        if (log_level >= LOG_SBEBUG12)
+            printk (">> init_comet: clockslave internal clock\n");
+        pci_write_32 ((u_int32_t *) &comet->tx_time, 0x0d);     /* oscillator timing */
+    }
+
+    /* 32: BRIF parity F-bit cfg */
+    /* Totem-pole operation */
+    pci_write_32 ((u_int32_t *) &comet->brif_pfcfg, 0x01);      /* Receive Backplane
+                                                                 * Parity/F-bit */
+
+    /* dc: RLPS equalizer V ref */
+    /* Configuration */
+    if (isT1mode)
+        pci_write_32 ((u_int32_t *) &comet->rlps_eqvr, 0x2c);   /* RLPS Equalizer
+                                                                 * Voltage  */
+    else
+        pci_write_32 ((u_int32_t *) &comet->rlps_eqvr, 0x34);   /* RLPS Equalizer
+                                                                 * Voltage  */
+
+    /* Reserved bit set and SQUELCH enabled */
+    /* f8: RLPS cfg & status  f9: RLPS ALOS detect/clear threshold */
+    pci_write_32 ((u_int32_t *) &comet->rlps_cfgsts, 0x11);     /* RLPS Configuration
+                                                                 * Status */
+    if (isT1mode)
+        pci_write_32 ((u_int32_t *) &comet->rlps_alos_thresh, 0x55);    /* ? */
+    else
+        pci_write_32 ((u_int32_t *) &comet->rlps_alos_thresh, 0x22);    /* ? */
+
+
+    /* Set Full Frame mode (NXDSO[1] = 0, NXDSO[0] = 0) */
+    /* CMODE=0: Clock slave mode with BTCLK as an input, DE=1: Use rising */
+    /* edge of BTCLK for data, FE=1: Use rising edge of BTCLK for frame, */
+    /* CMS=0: Use backplane freq, RATE[1:0]=0,0: T1 */
+/***    Transmit side is always an Input, Slave Clock*/
+    /* 40: BTIF cfg  41: BTIF frame pulse cfg */
+    if (isT1mode)
+        pci_write_32 ((u_int32_t *) &comet->btif_cfg, 0x38);    /* BTIF Configuration
+                                                                 * Reg. */
+    else
+        pci_write_32 ((u_int32_t *) &comet->btif_cfg, 0x39);    /* BTIF Configuration
+                                                                 * Reg. */
+
+    pci_write_32 ((u_int32_t *) &comet->btif_fpcfg, 0x01);      /* BTIF Frame Pulse
+                                                                 * Config. */
+
+    /* 0a: master diag  06: tx timing options */
+    /* if set Comet to loop back */
+
+    /* Comets set to normal */
+    pci_write_32 ((u_int32_t *) &comet->mdiag, 0x00);
+
+    /* BTCLK driven by TCLKI internally (crystal driven) and Xmt Elasted  */
+    /* Store is enabled. */
+
+    WrtXmtWaveformTbl (ci, comet, TWV_table[tix]);
+    if (isT1mode)
+        WrtRcvEqualizerTbl ((ci_t *) ci, comet, &T1_Equalizer[0]);
+    else
+        WrtRcvEqualizerTbl ((ci_t *) ci, comet, &E1_Equalizer[0]);
+    SetPwrLevel (comet);
+}
+
+/*
+** Name:        WrtXmtWaveform
+** Description: Formulate the Data for the Pulse Waveform Storage
+**                Write register, (F2), from the sample and unit inputs.
+**                Write the data to the Pulse Waveform Storage Data register.
+** Returns:     Nothing
+*/
+STATIC void
+WrtXmtWaveform (ci_t * ci, comet_t * comet, u_int32_t sample, u_int32_t unit, u_int8_t data)
+{
+    u_int8_t    WaveformAddr;
+
+    WaveformAddr = (sample << 3) + (unit & 7);
+    pci_write_32 ((u_int32_t *) &comet->xlpg_pwave_addr, WaveformAddr);
+    pci_flush_write (ci);           /* for write order preservation when
+                                     * Optimizing driver */
+    pci_write_32 ((u_int32_t *) &comet->xlpg_pwave_data, 0x7F & data);
+}
+
+/*
+** Name:        WrtXmtWaveformTbl
+** Description: Fill in the Transmit Waveform Values
+**                for driving the transmitter DAC.
+** Returns:     Nothing
+*/
+STATIC void
+WrtXmtWaveformTbl (ci_t * ci, comet_t * comet,
+                   u_int8_t table[COMET_NUM_SAMPLES][COMET_NUM_UNITS])
+{
+    u_int32_t sample, unit;
+
+    for (sample = 0; sample < COMET_NUM_SAMPLES; sample++)
+    {
+        for (unit = 0; unit < COMET_NUM_UNITS; unit++)
+            WrtXmtWaveform (ci, comet, sample, unit, table[sample][unit]);
+    }
+
+    /* Enable transmitter and set output amplitude */
+    pci_write_32 ((u_int32_t *) &comet->xlpg_cfg, table[COMET_NUM_SAMPLES][0]);
+}
+
+
+/*
+** Name:        WrtXmtWaveform
+** Description: Fill in the Receive Equalizer RAM from the desired
+**                table.
+** Returns:     Nothing
+**
+** Remarks:  Per PM4351 Device Errata, Receive Equalizer RAM Initialization
+**           is coded with early setup of indirect address.
+*/
+
+STATIC void
+WrtRcvEqualizerTbl (ci_t * ci, comet_t * comet, u_int32_t *table)
+{
+    u_int32_t   ramaddr;
+    volatile u_int32_t value;
+
+    for (ramaddr = 0; ramaddr < 256; ramaddr++)
+    {
+        /*** the following lines are per Errata 7, 2.5 ***/
+        {
+            pci_write_32 ((u_int32_t *) &comet->rlps_eq_rwsel, 0x80);   /* Set up for a read
+                                                                         * operation */
+            pci_flush_write (ci);   /* for write order preservation when
+                                     * Optimizing driver */
+            pci_write_32 ((u_int32_t *) &comet->rlps_eq_iaddr, (u_int8_t) ramaddr); /* write the addr,
+                                                                                  * initiate a read */
+            pci_flush_write (ci);   /* for write order preservation when
+                                     * Optimizing driver */
+            /*
+             * wait 3 line rate clock cycles to ensure address bits are
+             * captured by T1/E1 clock
+             */
+            OS_uwait (4, "wret");   /* 683ns * 3 = 1366 ns, approx 2us (but
+                                     * use 4us) */
+        }
+
+        value = *table++;
+        pci_write_32 ((u_int32_t *) &comet->rlps_idata3, (u_int8_t) (value >> 24));
+        pci_write_32 ((u_int32_t *) &comet->rlps_idata2, (u_int8_t) (value >> 16));
+        pci_write_32 ((u_int32_t *) &comet->rlps_idata1, (u_int8_t) (value >> 8));
+        pci_write_32 ((u_int32_t *) &comet->rlps_idata0, (u_int8_t) value);
+        pci_flush_write (ci);       /* for write order preservation when
+                                     * Optimizing driver */
+
+        /* Storing RAM address, causes RAM to be updated */
+
+        pci_write_32 ((u_int32_t *) &comet->rlps_eq_rwsel, 0);  /* Set up for a write
+                                                                 * operation */
+        pci_flush_write (ci);       /* for write order preservation when
+                                     * Optimizing driver */
+        pci_write_32 ((u_int32_t *) &comet->rlps_eq_iaddr, (u_int8_t) ramaddr); /* write the addr,
+                                                                                 * initiate a read */
+        pci_flush_write (ci);       /* for write order preservation when
+                                     * Optimizing driver */
+        /*
+         * wait 3 line rate clock cycles to ensure address bits are captured
+         * by T1/E1 clock
+         */
+        OS_uwait (4, "wret");       /* 683ns * 3 = 1366 ns, approx 2us (but
+                                     * use 4us) */
+    }
+
+    pci_write_32 ((u_int32_t *) &comet->rlps_eq_cfg, 0xCB);     /* Enable Equalizer &
+                                                                 * set it to use 256
+                                                                 * periods */
+}
+
+
+/*
+** Name:        SetPwrLevel
+** Description: Implement power level setting algorithm described below
+** Returns:     Nothing
+*/
+
+STATIC void
+SetPwrLevel (comet_t * comet)
+{
+    volatile u_int32_t temp;
+
+/*
+**    Algorithm to Balance the Power Distribution of Ttip Tring
+**
+**    Zero register F6
+**    Write 0x01 to register F4
+**    Write another 0x01 to register F4
+**    Read register F4
+**    Remove the 0x01 bit by Anding register F4 with 0xFE
+**    Write the resultant value to register F4
+**    Repeat these steps for register F5
+**    Write 0x01 to register F6
+*/
+    pci_write_32 ((u_int32_t *) &comet->xlpg_fdata_sel, 0x00);  /* XLPG Fuse Data Select */
+
+    pci_write_32 ((u_int32_t *) &comet->xlpg_atest_pctl, 0x01); /* XLPG Analog Test
+                                                                 * Positive control */
+    pci_write_32 ((u_int32_t *) &comet->xlpg_atest_pctl, 0x01);
+
+    temp = pci_read_32 ((u_int32_t *) &comet->xlpg_atest_pctl) & 0xfe;
+    pci_write_32 ((u_int32_t *) &comet->xlpg_atest_pctl, temp);
+
+    pci_write_32 ((u_int32_t *) &comet->xlpg_atest_nctl, 0x01); /* XLPG Analog Test
+                                                                 * Negative control */
+    pci_write_32 ((u_int32_t *) &comet->xlpg_atest_nctl, 0x01);
+
+    temp = pci_read_32 ((u_int32_t *) &comet->xlpg_atest_nctl) & 0xfe;
+    pci_write_32 ((u_int32_t *) &comet->xlpg_atest_nctl, temp);
+    pci_write_32 ((u_int32_t *) &comet->xlpg_fdata_sel, 0x01);  /* XLPG */
+}
+
+
+/*
+** Name:        SetCometOps
+** Description: Set up the selected Comet's clock edge drive for both
+**                the transmit out the analog side and receive to the
+**                backplane side.
+** Returns:     Nothing
+*/
+#if 0
+STATIC void
+SetCometOps (comet_t * comet)
+{
+    volatile u_int8_t rd_value;
+
+    if (comet == mConfig.C4Func1Base + (COMET0_OFFSET >> 2))
+    {
+        rd_value = (u_int8_t) pci_read_32 ((u_int32_t *) &comet->brif_cfg);     /* read the BRIF
+                                                                                 * Configuration */
+        rd_value &= ~0x20;
+        pci_write_32 ((u_int32_t *) &comet->brif_cfg, (u_int32_t) rd_value);
+
+        rd_value = (u_int8_t) pci_read_32 ((u_int32_t *) &comet->brif_fpcfg);   /* read the BRIF Frame
+                                                                                 * Pulse Configuration */
+        rd_value &= ~0x20;
+        pci_write_32 ((u_int32_t *) &comet->brif_fpcfg, (u_int8_t) rd_value);
+    } else
+    {
+        rd_value = (u_int8_t) pci_read_32 ((u_int32_t *) &comet->brif_cfg);     /* read the BRIF
+                                                                                 * Configuration */
+        rd_value |= 0x20;
+        pci_write_32 ((u_int32_t *) &comet->brif_cfg, (u_int32_t) rd_value);
+
+        rd_value = (u_int8_t) pci_read_32 ((u_int32_t *) &comet->brif_fpcfg);   /* read the BRIF Frame
+                                                                                 * Pulse Configuration */
+        rd_value |= 0x20;
+        pci_write_32 ((u_int32_t *) &comet->brif_fpcfg, (u_int8_t) rd_value);
+    }
+}
+#endif
+
+/***  End-of-File  ***/
diff --git a/drivers/staging/cxt1e1/comet.h b/drivers/staging/cxt1e1/comet.h
new file mode 100644 (file)
index 0000000..5cb3afd
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ * $Id: comet.h,v 1.3 2005/09/28 00:10:07 rickd PMCC4_3_1B $
+ */
+
+#ifndef _INC_COMET_H_
+#define _INC_COMET_H_
+
+/*-----------------------------------------------------------------------------
+ * comet.h -
+ *
+ * Copyright (C) 2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@sbei.com
+ * SBE, Inc.  San Ramon, California  U.S.A.
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 1.3 $
+ * Last changed on $Date: 2005/09/28 00:10:07 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: comet.h,v $
+ * Revision 1.3  2005/09/28 00:10:07  rickd
+ * Add RCS header. Switch to structure usage.
+ *
+ * Revision 1.2  2005/04/28 23:43:03  rickd
+ * Add RCS tracking heading.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#if defined(__FreeBSD__) || defined (__NetBSD__)
+#include <sys/types.h>
+#else
+#include <linux/types.h>
+#endif
+
+
+#define VINT32  volatile u_int32_t
+
+struct s_comet_reg
+{
+    VINT32 gbl_cfg;      /* 00  Global Cfg */
+    VINT32 clkmon;       /* 01  Clk Monitor */
+    VINT32 rx_opt;       /* 02  RX Options */
+    VINT32 rx_line_cfg;  /* 03  RX Line Interface Cfg */
+    VINT32 tx_line_cfg;  /* 04  TX Line Interface Cfg */
+    VINT32 tx_frpass;    /* 05  TX Framing & Bypass Options */
+    VINT32 tx_time;      /* 06  TX Timing Options */
+    VINT32 intr_1;       /* 07  Intr Source #1 */
+    VINT32 intr_2;       /* 08  Intr Source #2 */
+    VINT32 intr_3;       /* 09  Intr Source #3 */
+    VINT32 mdiag;        /* 0A  Master Diagnostics */
+    VINT32 mtest;        /* 0B  Master Test */
+    VINT32 adiag;        /* 0C  Analog Diagnostics */
+    VINT32 rev_id;       /* 0D  Rev/Chip Id/Global PMON Update */
+#define pmon  rev_id
+    VINT32 reset;        /* 0E  Reset */
+    VINT32 prgd_phctl;   /* 0F  PRGD Positioning/Ctl & HDLC Ctl */
+    VINT32 cdrc_cfg;     /* 10  CDRC Cfg */
+    VINT32 cdrc_ien;     /* 11  CDRC Intr Enable */
+    VINT32 cdrc_ists;    /* 12  CDRC Intr Sts */
+    VINT32 cdrc_alos;    /* 13  CDRC Alternate Loss of Signal */
+
+    VINT32 rjat_ists;    /* 14  RJAT Intr Sts */
+    VINT32 rjat_n1clk;   /* 15  RJAT Reference Clk Divisor (N1) Ctl */
+    VINT32 rjat_n2clk;   /* 16  RJAT Output Clk Divisor (N2) Ctl */
+    VINT32 rjat_cfg;     /* 17  RJAT Cfg */
+
+    VINT32 tjat_ists;    /* 18  TJAT Intr Sts */
+    VINT32 tjat_n1clk;   /* 19  TJAT Reference Clk Divisor (N1) Ctl */
+    VINT32 tjat_n2clk;   /* 1A  TJAT Output Clk Divisor (N2) Ctl */
+    VINT32 tjat_cfg;     /* 1B  TJAT Cfg */
+
+    VINT32 rx_elst_cfg;      /* 1C  RX-ELST Cfg */
+    VINT32 rx_elst_ists;     /* 1D  RX-ELST Intr Sts */
+    VINT32 rx_elst_idle;     /* 1E  RX-ELST Idle Code */
+    VINT32 _rx_elst_res1f;   /* 1F     RX-ELST Reserved */
+
+    VINT32 tx_elst_cfg;      /* 20  TX-ELST Cfg */
+    VINT32 tx_elst_ists;     /* 21  TX-ELST Intr Sts */
+    VINT32 _tx_elst_res22;   /* 22     TX-ELST Reserved */
+    VINT32 _tx_elst_res23;   /* 23     TX-ELST Reserved */
+    VINT32 __res24;          /* 24     Reserved */
+    VINT32 __res25;          /* 25     Reserved */
+    VINT32 __res26;          /* 26     Reserved */
+    VINT32 __res27;          /* 27     Reserved */
+
+    VINT32 rxce1_ctl;        /* 28  RXCE RX Data Link 1 Ctl */
+    VINT32 rxce1_bits;       /* 29  RXCE RX Data Link 1 Bit Select */
+    VINT32 rxce2_ctl;        /* 2A  RXCE RX Data Link 2 Ctl */
+    VINT32 rxce2_bits;       /* 2B  RXCE RX Data Link 2 Bit Select */
+    VINT32 rxce3_ctl;        /* 2C  RXCE RX Data Link 3 Ctl */
+    VINT32 rxce3_bits;       /* 2D  RXCE RX Data Link 3 Bit Select */
+    VINT32 _rxce_res2E;      /* 2E     RXCE Reserved */
+    VINT32 _rxce_res2F;      /* 2F     RXCE Reserved */
+
+    VINT32 brif_cfg;         /* 30  BRIF RX Backplane Cfg */
+    VINT32 brif_fpcfg;       /* 31  BRIF RX Backplane Frame Pulse Cfg */
+    VINT32 brif_pfcfg;       /* 32  BRIF RX Backplane Parity/F-Bit Cfg */
+    VINT32 brif_tsoff;       /* 33  BRIF RX Backplane Time Slot Offset */
+    VINT32 brif_boff;        /* 34  BRIF RX Backplane Bit Offset */
+    VINT32 _brif_res35;      /* 35     BRIF RX Backplane Reserved */
+    VINT32 _brif_res36;      /* 36     BRIF RX Backplane Reserved */
+    VINT32 _brif_res37;      /* 37     BRIF RX Backplane Reserved */
+
+    VINT32 txci1_ctl;        /* 38  TXCI TX Data Link 1 Ctl */
+    VINT32 txci1_bits;       /* 39  TXCI TX Data Link 2 Bit Select */
+    VINT32 txci2_ctl;        /* 3A  TXCI TX Data Link 1 Ctl */
+    VINT32 txci2_bits;       /* 3B  TXCI TX Data Link 2 Bit Select */
+    VINT32 txci3_ctl;        /* 3C  TXCI TX Data Link 1 Ctl */
+    VINT32 txci3_bits;       /* 3D  TXCI TX Data Link 2 Bit Select */
+    VINT32 _txci_res3E;      /* 3E     TXCI Reserved */
+    VINT32 _txci_res3F;      /* 3F     TXCI Reserved */
+
+    VINT32 btif_cfg;         /* 40  BTIF TX Backplane Cfg */
+    VINT32 btif_fpcfg;       /* 41  BTIF TX Backplane Frame Pulse Cfg */
+    VINT32 btif_pcfgsts;     /* 42  BTIF TX Backplane Parity Cfg & Sts */
+    VINT32 btif_tsoff;       /* 43  BTIF TX Backplane Time Slot Offset */
+    VINT32 btif_boff;        /* 44  BTIF TX Backplane Bit Offset */
+    VINT32 _btif_res45;      /* 45     BTIF TX Backplane Reserved */
+    VINT32 _btif_res46;      /* 46     BTIF TX Backplane Reserved */
+    VINT32 _btif_res47;      /* 47     BTIF TX Backplane Reserved */
+    VINT32 t1_frmr_cfg;      /* 48  T1 FRMR Cfg */
+    VINT32 t1_frmr_ien;      /* 49  T1 FRMR Intr Enable */
+    VINT32 t1_frmr_ists;     /* 4A  T1 FRMR Intr Sts */
+    VINT32 __res_4B;         /* 4B     Reserved */
+    VINT32 ibcd_cfg;         /* 4C  IBCD Cfg */
+    VINT32 ibcd_ies;         /* 4D  IBCD Intr Enable/Sts */
+    VINT32 ibcd_act;         /* 4E  IBCD Activate Code */
+    VINT32 ibcd_deact;       /* 4F  IBCD Deactivate Code */
+
+    VINT32 sigx_cfg;         /* 50  SIGX Cfg/Change of Signaling State */
+    VINT32 sigx_acc_cos;     /* 51  SIGX uP Access Sts/Change of Signaling State */
+    VINT32 sigx_iac_cos;     /* 52  SIGX Channel Indirect
+                              * Addr/Ctl/Change of Signaling State */
+    VINT32 sigx_idb_cos;     /* 53  SIGX Channel Indirect Data
+                              * Buffer/Change of Signaling State */
+
+    VINT32 t1_xbas_cfg;      /* 54  T1 XBAS Cfg */
+    VINT32 t1_xbas_altx;     /* 55  T1 XBAS Alarm TX */
+    VINT32 t1_xibc_ctl;      /* 56  T1 XIBC Ctl */
+    VINT32 t1_xibc_lbcode;   /* 57  T1 XIBC Loopback Code */
+
+    VINT32 pmon_ies;         /* 58  PMON Intr Enable/Sts */
+    VINT32 pmon_fberr;       /* 59  PMON Framing Bit Err Cnt */
+    VINT32 pmon_feb_lsb;     /* 5A  PMON OFF/COFA/Far End Block Err Cnt (LSB) */
+    VINT32 pmon_feb_msb;     /* 5B  PMON OFF/COFA/Far End Block Err Cnt (MSB) */
+    VINT32 pmon_bed_lsb;     /* 5C  PMON Bit/Err/CRCE Cnt (LSB) */
+    VINT32 pmon_bed_msb;     /* 5D  PMON Bit/Err/CRCE Cnt (MSB) */
+    VINT32 pmon_lvc_lsb;     /* 5E  PMON LVC Cnt (LSB) */
+    VINT32 pmon_lvc_msb;     /* 5F  PMON LVC Cnt (MSB) */
+
+    VINT32 t1_almi_cfg;      /* 60  T1 ALMI Cfg */
+    VINT32 t1_almi_ien;      /* 61  T1 ALMI Intr Enable */
+    VINT32 t1_almi_ists;     /* 62  T1 ALMI Intr Sts */
+    VINT32 t1_almi_detsts;   /* 63  T1 ALMI Alarm Detection Sts */
+
+    VINT32 _t1_pdvd_res64;   /* 64     T1 PDVD Reserved */
+    VINT32 t1_pdvd_ies;      /* 65  T1 PDVD Intr Enable/Sts */
+    VINT32 _t1_xboc_res66;   /* 66     T1 XBOC Reserved */
+    VINT32 t1_xboc_code;     /* 67  T1 XBOC Code */
+    VINT32 _t1_xpde_res68;   /* 68     T1 XPDE Reserved */
+    VINT32 t1_xpde_ies;      /* 69  T1 XPDE Intr Enable/Sts */
+
+    VINT32 t1_rboc_ena;      /* 6A  T1 RBOC Enable */
+    VINT32 t1_rboc_sts;      /* 6B  T1 RBOC Code Sts */
+
+    VINT32 t1_tpsc_cfg;      /* 6C  TPSC Cfg */
+    VINT32 t1_tpsc_sts;      /* 6D  TPSC uP Access Sts */
+    VINT32 t1_tpsc_ciaddr;   /* 6E  TPSC Channel Indirect
+                                          * Addr/Ctl */
+    VINT32 t1_tpsc_cidata;   /* 6F  TPSC Channel Indirect Data
+                                          * Buffer */
+    VINT32 t1_rpsc_cfg;      /* 70  RPSC Cfg */
+    VINT32 t1_rpsc_sts;      /* 71  RPSC uP Access Sts */
+    VINT32 t1_rpsc_ciaddr;   /* 72  RPSC Channel Indirect
+                                          * Addr/Ctl */
+    VINT32 t1_rpsc_cidata;   /* 73  RPSC Channel Indirect Data
+                                          * Buffer */
+    VINT32 __res74;          /* 74     Reserved */
+    VINT32 __res75;          /* 75     Reserved */
+    VINT32 __res76;          /* 76     Reserved */
+    VINT32 __res77;          /* 77     Reserved */
+
+    VINT32 t1_aprm_cfg;      /* 78  T1 APRM Cfg/Ctl */
+    VINT32 t1_aprm_load;     /* 79  T1 APRM Manual Load */
+    VINT32 t1_aprm_ists;     /* 7A  T1 APRM Intr Sts */
+    VINT32 t1_aprm_1sec_2;   /* 7B  T1 APRM One Second Content Octet 2 */
+    VINT32 t1_aprm_1sec_3;   /* 7C  T1 APRM One Second Content Octet 3 */
+    VINT32 t1_aprm_1sec_4;   /* 7D  T1 APRM One Second Content Octet 4 */
+    VINT32 t1_aprm_1sec_5;   /* 7E  T1 APRM One Second Content MSB (Octect 5) */
+    VINT32 t1_aprm_1sec_6;   /* 7F  T1 APRM One Second Content MSB (Octect 6) */
+
+    VINT32 e1_tran_cfg;      /* 80  E1 TRAN Cfg */
+    VINT32 e1_tran_txalarm;  /* 81  E1 TRAN TX Alarm/Diagnostic Ctl */
+    VINT32 e1_tran_intctl;   /* 82  E1 TRAN International Ctl */
+    VINT32 e1_tran_extrab;   /* 83  E1 TRAN Extra Bits Ctl */
+    VINT32 e1_tran_ien;      /* 84  E1 TRAN Intr Enable */
+    VINT32 e1_tran_ists;     /* 85  E1 TRAN Intr Sts */
+    VINT32 e1_tran_nats;     /* 86  E1 TRAN National Bit Codeword
+                                          * Select */
+    VINT32 e1_tran_nat;      /* 87  E1 TRAN National Bit Codeword */
+    VINT32 __res88;          /* 88     Reserved */
+    VINT32 __res89;          /* 89     Reserved */
+    VINT32 __res8A;          /* 8A     Reserved */
+    VINT32 __res8B;          /* 8B     Reserved */
+
+    VINT32 _t1_frmr_res8C;   /* 8C     T1 FRMR Reserved */
+    VINT32 _t1_frmr_res8D;   /* 8D     T1 FRMR Reserved */
+    VINT32 __res8E;          /* 8E     Reserved */
+    VINT32 __res8F;          /* 8F     Reserved */
+
+    VINT32 e1_frmr_aopts;    /* 90  E1 FRMR Frame Alignment Options */
+    VINT32 e1_frmr_mopts;    /* 91  E1 FRMR Maintenance Mode Options */
+    VINT32 e1_frmr_ien;      /* 92  E1 FRMR Framing Sts Intr Enable */
+    VINT32 e1_frmr_mien;     /* 93  E1 FRMR Maintenance/Alarm Sts Intr Enable */
+    VINT32 e1_frmr_ists;     /* 94  E1 FRMR Framing Sts Intr Indication */
+    VINT32 e1_frmr_mists;    /* 95  E1 FRMR Maintenance/Alarm Sts Indication Enable */
+    VINT32 e1_frmr_sts;      /* 96  E1 FRMR Framing Sts */
+    VINT32 e1_frmr_masts;    /* 97  E1 FRMR Maintenance/Alarm Sts */
+    VINT32 e1_frmr_nat_bits; /* 98  E1 FRMR International/National Bits */
+    VINT32 e1_frmr_crc_lsb;  /* 99  E1 FRMR CRC Err Cnt - LSB */
+    VINT32 e1_frmr_crc_msb;  /* 9A  E1 FRMR CRC Err Cnt - MSB */
+    VINT32 e1_frmr_nat_ien;  /* 9B  E1 FRMR National Bit Codeword Intr Enables */
+    VINT32 e1_frmr_nat_ists; /* 9C  E1 FRMR National Bit Codeword Intr/Sts */
+    VINT32 e1_frmr_nat;      /* 9D  E1 FRMR National Bit Codewords */
+    VINT32 e1_frmr_fp_ien;   /* 9E  E1 FRMR Frame Pulse/Alarm Intr Enables */
+    VINT32 e1_frmr_fp_ists;  /* 9F  E1 FRMR Frame Pulse/Alarm Intr/Sts */
+
+    VINT32 __resA0;          /* A0     Reserved */
+    VINT32 __resA1;          /* A1     Reserved */
+    VINT32 __resA2;          /* A2     Reserved */
+    VINT32 __resA3;          /* A3     Reserved */
+    VINT32 __resA4;          /* A4     Reserved */
+    VINT32 __resA5;          /* A5     Reserved */
+    VINT32 __resA6;          /* A6     Reserved */
+    VINT32 __resA7;          /* A7     Reserved */
+
+    VINT32 tdpr1_cfg;        /* A8  TDPR #1 Cfg */
+    VINT32 tdpr1_utl;        /* A9  TDPR #1 Upper TX Threshold */
+    VINT32 tdpr1_ltl;        /* AA  TDPR #1 Lower TX Threshold */
+    VINT32 tdpr1_ien;        /* AB  TDPR #1 Intr Enable */
+    VINT32 tdpr1_ists;       /* AC  TDPR #1 Intr Sts/UDR Clear */
+    VINT32 tdpr1_data;       /* AD  TDPR #1 TX Data */
+    VINT32 __resAE;          /* AE     Reserved */
+    VINT32 __resAF;          /* AF     Reserved */
+    VINT32 tdpr2_cfg;        /* B0  TDPR #2 Cfg */
+    VINT32 tdpr2_utl;        /* B1  TDPR #2 Upper TX Threshold */
+    VINT32 tdpr2_ltl;        /* B2  TDPR #2 Lower TX Threshold */
+    VINT32 tdpr2_ien;        /* B3  TDPR #2 Intr Enable */
+    VINT32 tdpr2_ists;       /* B4  TDPR #2 Intr Sts/UDR Clear */
+    VINT32 tdpr2_data;       /* B5  TDPR #2 TX Data */
+    VINT32 __resB6;          /* B6     Reserved */
+    VINT32 __resB7;          /* B7     Reserved1 */
+    VINT32 tdpr3_cfg;        /* B8  TDPR #3 Cfg */
+    VINT32 tdpr3_utl;        /* B9  TDPR #3 Upper TX Threshold */
+    VINT32 tdpr3_ltl;        /* BA  TDPR #3 Lower TX Threshold */
+    VINT32 tdpr3_ien;        /* BB  TDPR #3 Intr Enable */
+    VINT32 tdpr3_ists;       /* BC  TDPR #3 Intr Sts/UDR Clear */
+    VINT32 tdpr3_data;       /* BD  TDPR #3 TX Data */
+    VINT32 __resBE;          /* BE     Reserved */
+    VINT32 __resBF;          /* BF     Reserved */
+
+    VINT32 rdlc1_cfg;        /* C0  RDLC #1 Cfg */
+    VINT32 rdlc1_intctl;     /* C1  RDLC #1 Intr Ctl */
+    VINT32 rdlc1_sts;        /* C2  RDLC #1 Sts */
+    VINT32 rdlc1_data;       /* C3  RDLC #1 Data */
+    VINT32 rdlc1_paddr;      /* C4  RDLC #1 Primary Addr Match */
+    VINT32 rdlc1_saddr;      /* C5  RDLC #1 Secondary Addr Match */
+    VINT32 __resC6;          /* C6     Reserved */
+    VINT32 __resC7;          /* C7     Reserved */
+    VINT32 rdlc2_cfg;        /* C8  RDLC #2 Cfg */
+    VINT32 rdlc2_intctl;     /* C9  RDLC #2 Intr Ctl */
+    VINT32 rdlc2_sts;        /* CA  RDLC #2 Sts */
+    VINT32 rdlc2_data;       /* CB  RDLC #2 Data */
+    VINT32 rdlc2_paddr;      /* CC  RDLC #2 Primary Addr Match */
+    VINT32 rdlc2_saddr;      /* CD  RDLC #2 Secondary Addr Match */
+    VINT32 __resCE;          /* CE     Reserved */
+    VINT32 __resCF;          /* CF     Reserved */
+    VINT32 rdlc3_cfg;        /* D0  RDLC #3 Cfg */
+    VINT32 rdlc3_intctl;     /* D1  RDLC #3 Intr Ctl */
+    VINT32 rdlc3_sts;        /* D2  RDLC #3 Sts */
+    VINT32 rdlc3_data;       /* D3  RDLC #3 Data */
+    VINT32 rdlc3_paddr;      /* D4  RDLC #3 Primary Addr Match */
+    VINT32 rdlc3_saddr;      /* D5  RDLC #3 Secondary Addr Match */
+
+    VINT32 csu_cfg;          /* D6  CSU Cfg */
+    VINT32 _csu_resD7;       /* D7     CSU Reserved */
+
+    VINT32 rlps_idata3;      /* D8  RLPS Indirect Data, 24-31 */
+    VINT32 rlps_idata2;      /* D9  RLPS Indirect Data, 16-23 */
+    VINT32 rlps_idata1;      /* DA  RLPS Indirect Data, 8-15 */
+    VINT32 rlps_idata0;      /* DB  RLPS Indirect Data, 0-7 */
+    VINT32 rlps_eqvr;        /* DC  RLPS Equalizer Voltage Reference
+                              *    (E1 missing) */
+    VINT32 _rlps_resDD;      /* DD     RLPS Reserved */
+    VINT32 _rlps_resDE;      /* DE     RLPS Reserved */
+    VINT32 _rlps_resDF;      /* DF     RLPS Reserved */
+
+    VINT32 prgd_ctl;         /* E0  PRGD Ctl */
+    VINT32 prgd_ies;         /* E1  PRGD Intr Enable/Sts */
+    VINT32 prgd_shift_len;   /* E2  PRGD Shift Length */
+    VINT32 prgd_tap;         /* E3  PRGD Tap */
+    VINT32 prgd_errin;       /* E4  PRGD Err Insertion */
+    VINT32 _prgd_resE5;      /* E5     PRGD Reserved */
+    VINT32 _prgd_resE6;      /* E6     PRGD Reserved */
+    VINT32 _prgd_resE7;      /* E7     PRGD Reserved */
+    VINT32 prgd_patin1;      /* E8  PRGD Pattern Insertion #1 */
+    VINT32 prgd_patin2;      /* E9  PRGD Pattern Insertion #2 */
+    VINT32 prgd_patin3;      /* EA  PRGD Pattern Insertion #3 */
+    VINT32 prgd_patin4;      /* EB  PRGD Pattern Insertion #4 */
+    VINT32 prgd_patdet1;     /* EC  PRGD Pattern Detector #1 */
+    VINT32 prgd_patdet2;     /* ED  PRGD Pattern Detector #2 */
+    VINT32 prgd_patdet3;     /* EE  PRGD Pattern Detector #3 */
+    VINT32 prgd_patdet4;     /* EF  PRGD Pattern Detector #4 */
+
+    VINT32 xlpg_cfg;         /* F0  XLPG Line Driver Cfg */
+    VINT32 xlpg_ctlsts;      /* F1  XLPG Ctl/Sts */
+    VINT32 xlpg_pwave_addr;  /* F2  XLPG Pulse Waveform Storage Write Addr */
+    VINT32 xlpg_pwave_data;  /* F3  XLPG Pulse Waveform Storage Data */
+    VINT32 xlpg_atest_pctl;  /* F4  XLPG Analog Test Positive Ctl */
+    VINT32 xlpg_atest_nctl;  /* F5  XLPG Analog Test Negative Ctl */
+    VINT32 xlpg_fdata_sel;   /* F6  XLPG Fuse Data Select */
+    VINT32 _xlpg_resF7;      /* F7     XLPG Reserved */
+
+    VINT32 rlps_cfgsts;      /* F8  RLPS Cfg & Sts */
+    VINT32 rlps_alos_thresh; /* F9  RLPS ALOS Detection/Clearance Threshold */
+    VINT32 rlps_alos_dper;   /* FA  RLPS ALOS Detection Period */
+    VINT32 rlps_alos_cper;   /* FB  RLPS ALOS Clearance Period */
+    VINT32 rlps_eq_iaddr;    /* FC  RLPS Equalization Indirect Addr */
+    VINT32 rlps_eq_rwsel;    /* FD  RLPS Equalization Read/WriteB Select */
+    VINT32 rlps_eq_ctlsts;   /* FE  RLPS Equalizer Loop Sts & Ctl */
+    VINT32 rlps_eq_cfg;      /* FF  RLPS Equalizer Cfg */
+};
+
+typedef struct s_comet_reg comet_t;
+
+/* 00AH: MDIAG Register bit definitions */
+#define COMET_MDIAG_ID5        0x40
+#define COMET_MDIAG_LBMASK     0x3F
+#define COMET_MDIAG_PAYLB      0x20
+#define COMET_MDIAG_LINELB     0x10
+#define COMET_MDIAG_RAIS       0x08
+#define COMET_MDIAG_DDLB       0x04
+#define COMET_MDIAG_TXMFP      0x02
+#define COMET_MDIAG_TXLOS      0x01
+#define COMET_MDIAG_LBOFF      0x00
+
+#undef VINT32
+
+#ifdef __KERNEL__
+extern void
+init_comet (void *, comet_t *, u_int32_t, int, u_int8_t);
+#endif
+
+#endif                          /* _INC_COMET_H_ */
diff --git a/drivers/staging/cxt1e1/comet_tables.c b/drivers/staging/cxt1e1/comet_tables.c
new file mode 100644 (file)
index 0000000..db1293c
--- /dev/null
@@ -0,0 +1,561 @@
+/*
+ * $Id: comet_tables.c,v 1.2 2005/10/17 23:55:27 rickd PMCC4_3_1B $
+ */
+
+/*-----------------------------------------------------------------------------
+ * comet_tables.c - waveform tables for the PM4351 'COMET'
+ *
+ * Copyright (C) 2003-2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@sbei.com
+ * SBE, Inc.  San Ramon, California  U.S.A.
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 1.2 $
+ * Last changed on $Date: 2005/10/17 23:55:27 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: comet_tables.c,v $
+ * Revision 1.2  2005/10/17 23:55:27  rickd
+ * Note that 75 Ohm transmit waveform is not supported on PMCC4.
+ *
+ * Revision 1.1  2005/09/28 00:10:05  rickd
+ * Cosmetic alignment of tables for readability.
+ *
+ * Revision 1.0  2005/05/10 22:47:53  rickd
+ * Initial revision
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+char SBEid_pmcc4_comet_tblc[] =
+  "@(#)comet_tables.c - $Revision: 1.2 $      (c) Copyright 2004-2005 SBE, Inc.";
+
+
+#include <linux/types.h>
+
+/*****************************************************************************
+*
+*  Array names:
+*
+*       TWVLongHaul0DB
+*       TWVLongHaul7_5DB
+*       TWVLongHaul15DB
+*       TWVLongHaul22_5DB
+*       TWVShortHaul0
+*       TWVShortHaul1
+*       TWVShortHaul2
+*       TWVShortHaul3
+*       TWVShortHaul4
+*       TWVShortHaul5
+*       TWV_E1_120Ohm
+*       TWV_E1_75Ohm   <not supported>
+*       T1_Equalizer
+*       E1_Equalizer
+*
+*****************************************************************************/
+
+u_int8_t TWVLongHaul0DB[25][5] =/* T1 Long Haul 0 DB */
+{
+    {0x00, 0x44, 0x00, 0x00, 0x00},     /* Sample 0 */
+    {0x0A, 0x44, 0x00, 0x00, 0x00},     /* Sample 1 */
+    {0x20, 0x43, 0x00, 0x00, 0x00},     /* Sample 2 */
+    {0x32, 0x43, 0x00, 0x00, 0x00},     /* Sample 3 */
+    {0x3E, 0x42, 0x00, 0x00, 0x00},     /* Sample 4 */
+    {0x3D, 0x42, 0x00, 0x00, 0x00},     /* Sample 5 */
+    {0x3C, 0x41, 0x00, 0x00, 0x00},     /* Sample 6 */
+    {0x3B, 0x41, 0x00, 0x00, 0x00},     /* Sample 7 */
+    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
+    {0x39, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
+    {0x39, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
+    {0x38, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
+    {0x37, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
+    {0x36, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
+    {0x34, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
+    {0x29, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
+    {0x4F, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
+    {0x4C, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
+    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
+    {0x49, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
+    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
+    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
+    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
+    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
+    {0x0C}                              /* PMC's suggested value */
+/*  {0x14}                    Output Amplitude */
+};
+
+u_int8_t    TWVLongHaul7_5DB[25][5] =   /* T1 Long Haul 7.5 DB */
+{
+    {0x00, 0x10, 0x00, 0x00, 0x00},     /* Sample 0 */
+    {0x01, 0x0E, 0x00, 0x00, 0x00},     /* Sample 1 */
+    {0x02, 0x0C, 0x00, 0x00, 0x00},     /* Sample 2 */
+    {0x04, 0x0A, 0x00, 0x00, 0x00},     /* Sample 3 */
+    {0x08, 0x08, 0x00, 0x00, 0x00},     /* Sample 4 */
+    {0x0C, 0x06, 0x00, 0x00, 0x00},     /* Sample 5 */
+    {0x10, 0x04, 0x00, 0x00, 0x00},     /* Sample 6 */
+    {0x16, 0x02, 0x00, 0x00, 0x00},     /* Sample 7 */
+    {0x1A, 0x01, 0x00, 0x00, 0x00},     /* Sample 8 */
+    {0x1E, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
+    {0x22, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
+    {0x26, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
+    {0x2A, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
+    {0x2B, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
+    {0x2C, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
+    {0x2D, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
+    {0x2C, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
+    {0x28, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
+    {0x24, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
+    {0x20, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
+    {0x1C, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
+    {0x18, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
+    {0x14, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
+    {0x12, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
+    {0x07}                      /* PMC's suggested value */
+/*  { 0x0A }                        Output Amplitude */
+};
+
+u_int8_t    TWVLongHaul15DB[25][5] =    /* T1 Long Haul 15 DB */
+{
+    {0x00, 0x2A, 0x09, 0x01, 0x00},     /* Sample 0 */
+    {0x00, 0x28, 0x08, 0x01, 0x00},     /* Sample 1 */
+    {0x00, 0x26, 0x08, 0x01, 0x00},     /* Sample 2 */
+    {0x00, 0x24, 0x07, 0x01, 0x00},     /* Sample 3 */
+    {0x01, 0x22, 0x07, 0x01, 0x00},     /* Sample 4 */
+    {0x02, 0x20, 0x06, 0x01, 0x00},     /* Sample 5 */
+    {0x04, 0x1E, 0x06, 0x01, 0x00},     /* Sample 6 */
+    {0x07, 0x1C, 0x05, 0x00, 0x00},     /* Sample 7 */
+    {0x0A, 0x1B, 0x05, 0x00, 0x00},     /* Sample 8 */
+    {0x0D, 0x19, 0x05, 0x00, 0x00},     /* Sample 9 */
+    {0x10, 0x18, 0x04, 0x00, 0x00},     /* Sample 10 */
+    {0x14, 0x16, 0x04, 0x00, 0x00},     /* Sample 11 */
+    {0x18, 0x15, 0x04, 0x00, 0x00},     /* Sample 12 */
+    {0x1B, 0x13, 0x03, 0x00, 0x00},     /* Sample 13 */
+    {0x1E, 0x12, 0x03, 0x00, 0x00},     /* Sample 14 */
+    {0x21, 0x10, 0x03, 0x00, 0x00},     /* Sample 15 */
+    {0x24, 0x0F, 0x03, 0x00, 0x00},     /* Sample 16 */
+    {0x27, 0x0D, 0x03, 0x00, 0x00},     /* Sample 17 */
+    {0x2A, 0x0D, 0x02, 0x00, 0x00},     /* Sample 18 */
+    {0x2D, 0x0B, 0x02, 0x00, 0x00},     /* Sample 19 */
+    {0x30, 0x0B, 0x02, 0x00, 0x00},     /* Sample 20 */
+    {0x30, 0x0A, 0x02, 0x00, 0x00},     /* Sample 21 */
+    {0x2E, 0x0A, 0x02, 0x00, 0x00},     /* Sample 22 */
+    {0x2C, 0x09, 0x02, 0x00, 0x00},     /* Sample 23 */
+    {0x03}                      /* Output Amplitude */
+};
+
+u_int8_t    TWVLongHaul22_5DB[25][5] =  /* T1 Long Haul 22.5 DB */
+{
+    {0x00, 0x1F, 0x16, 0x06, 0x01},     /* Sample 0 */
+    {0x00, 0x20, 0x15, 0x05, 0x01},     /* Sample 1 */
+    {0x00, 0x21, 0x15, 0x05, 0x01},     /* Sample 2 */
+    {0x00, 0x22, 0x14, 0x05, 0x01},     /* Sample 3 */
+    {0x00, 0x22, 0x13, 0x04, 0x00},     /* Sample 4 */
+    {0x00, 0x23, 0x12, 0x04, 0x00},     /* Sample 5 */
+    {0x01, 0x23, 0x12, 0x04, 0x00},     /* Sample 6 */
+    {0x01, 0x24, 0x11, 0x03, 0x00},     /* Sample 7 */
+    {0x01, 0x23, 0x10, 0x03, 0x00},     /* Sample 8 */
+    {0x02, 0x23, 0x10, 0x03, 0x00},     /* Sample 9 */
+    {0x03, 0x22, 0x0F, 0x03, 0x00},     /* Sample 10 */
+    {0x05, 0x22, 0x0E, 0x03, 0x00},     /* Sample 11 */
+    {0x07, 0x21, 0x0E, 0x02, 0x00},     /* Sample 12 */
+    {0x09, 0x20, 0x0D, 0x02, 0x00},     /* Sample 13 */
+    {0x0B, 0x1E, 0x0C, 0x02, 0x00},     /* Sample 14 */
+    {0x0E, 0x1D, 0x0C, 0x02, 0x00},     /* Sample 15 */
+    {0x10, 0x1B, 0x0B, 0x02, 0x00},     /* Sample 16 */
+    {0x13, 0x1B, 0x0A, 0x02, 0x00},     /* Sample 17 */
+    {0x15, 0x1A, 0x0A, 0x02, 0x00},     /* Sample 18 */
+    {0x17, 0x19, 0x09, 0x01, 0x00},     /* Sample 19 */
+    {0x19, 0x19, 0x08, 0x01, 0x00},     /* Sample 20 */
+    {0x1B, 0x18, 0x08, 0x01, 0x00},     /* Sample 21 */
+    {0x1D, 0x17, 0x07, 0x01, 0x00},     /* Sample 22 */
+    {0x1E, 0x17, 0x06, 0x01, 0x00},     /* Sample 23 */
+    {0x02}                      /* Output Amplitude */
+};
+
+u_int8_t    TWVShortHaul0[25][5] =      /* T1 Short Haul 0 - 110 ft */
+{
+    {0x00, 0x45, 0x00, 0x00, 0x00},     /* Sample 0 */
+    {0x0A, 0x44, 0x00, 0x00, 0x00},     /* Sample 1 */
+    {0x20, 0x43, 0x00, 0x00, 0x00},     /* Sample 2 */
+    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 3 */
+    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 4 */
+    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 5 */
+    {0x3C, 0x41, 0x00, 0x00, 0x00},     /* Sample 6 */
+    {0x3B, 0x41, 0x00, 0x00, 0x00},     /* Sample 7 */
+    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
+    {0x39, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
+    {0x39, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
+    {0x38, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
+    {0x37, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
+    {0x36, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
+    {0x34, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
+    {0x29, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
+    {0x59, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
+    {0x55, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
+    {0x50, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
+    {0x4D, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
+    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
+    {0x48, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
+    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
+    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
+    {0x0C}                      /* Output Amplitude */
+};
+
+u_int8_t    TWVShortHaul1[25][5] =      /* T1 Short Haul 110 - 220 ft */
+{
+    {0x00, 0x44, 0x00, 0x00, 0x00},     /* Sample 0 */
+    {0x0A, 0x44, 0x00, 0x00, 0x00},     /* Sample 1 */
+    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 2 */
+    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 3 */
+    {0x36, 0x42, 0x00, 0x00, 0x00},     /* Sample 4 */
+    {0x34, 0x42, 0x00, 0x00, 0x00},     /* Sample 5 */
+    {0x30, 0x41, 0x00, 0x00, 0x00},     /* Sample 6 */
+    {0x2F, 0x41, 0x00, 0x00, 0x00},     /* Sample 7 */
+    {0x2E, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
+    {0x2D, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
+    {0x2C, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
+    {0x2B, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
+    {0x2A, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
+    {0x28, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
+    {0x26, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
+    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
+    {0x68, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
+    {0x54, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
+    {0x4F, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
+    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
+    {0x49, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
+    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
+    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
+    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
+    {0x10}                      /* Output Amplitude */
+};
+
+u_int8_t    TWVShortHaul2[25][5] =      /* T1 Short Haul 220 - 330 ft */
+{
+    {0x00, 0x44, 0x00, 0x00, 0x00},     /* Sample 0 */
+    {0x0A, 0x44, 0x00, 0x00, 0x00},     /* Sample 1 */
+    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 2 */
+    {0x3A, 0x43, 0x00, 0x00, 0x00},     /* Sample 3 */
+    {0x3A, 0x42, 0x00, 0x00, 0x00},     /* Sample 4 */
+    {0x38, 0x42, 0x00, 0x00, 0x00},     /* Sample 5 */
+    {0x30, 0x41, 0x00, 0x00, 0x00},     /* Sample 6 */
+    {0x2F, 0x41, 0x00, 0x00, 0x00},     /* Sample 7 */
+    {0x2E, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
+    {0x2D, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
+    {0x2C, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
+    {0x2B, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
+    {0x2A, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
+    {0x29, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
+    {0x23, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
+    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
+    {0x6C, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
+    {0x60, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
+    {0x4F, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
+    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
+    {0x49, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
+    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
+    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
+    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
+    {0x11}                      /* Output Amplitude */
+};
+
+u_int8_t    TWVShortHaul3[25][5] =      /* T1 Short Haul 330 - 440 ft */
+{
+    {0x00, 0x44, 0x00, 0x00, 0x00},     /* Sample 0 */
+    {0x0A, 0x44, 0x00, 0x00, 0x00},     /* Sample 1 */
+    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 2 */
+    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 3 */
+    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 4 */
+    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 5 */
+    {0x2F, 0x41, 0x00, 0x00, 0x00},     /* Sample 6 */
+    {0x2E, 0x41, 0x00, 0x00, 0x00},     /* Sample 7 */
+    {0x2D, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
+    {0x2C, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
+    {0x2B, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
+    {0x2A, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
+    {0x29, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
+    {0x28, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
+    {0x19, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
+    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
+    {0x7F, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
+    {0x60, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
+    {0x4F, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
+    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
+    {0x49, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
+    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
+    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
+    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
+    {0x12}                      /* Output Amplitude */
+};
+
+u_int8_t    TWVShortHaul4[25][5] =      /* T1 Short Haul 440 - 550 ft */
+{
+    {0x00, 0x44, 0x00, 0x00, 0x00},     /* Sample 0 */
+    {0x0A, 0x44, 0x00, 0x00, 0x00},     /* Sample 1 */
+    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 2 */
+    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 3 */
+    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 4 */
+    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 5 */
+    {0x30, 0x41, 0x00, 0x00, 0x00},     /* Sample 6 */
+    {0x2B, 0x41, 0x00, 0x00, 0x00},     /* Sample 7 */
+    {0x2A, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
+    {0x29, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
+    {0x28, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
+    {0x27, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
+    {0x26, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
+    {0x26, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
+    {0x24, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
+    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
+    {0x7F, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
+    {0x7F, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
+    {0x4F, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
+    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
+    {0x49, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
+    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
+    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
+    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
+    {0x14}                      /* Output Amplitude */
+};
+
+u_int8_t    TWVShortHaul5[25][5] =      /* T1 Short Haul 550 - 660 ft */
+{
+    {0x00, 0x44, 0x00, 0x00, 0x00},     /* Sample 0 */
+    {0x0A, 0x44, 0x00, 0x00, 0x00},     /* Sample 1 */
+    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 2 */
+    {0x3F, 0x43, 0x00, 0x00, 0x00},     /* Sample 3 */
+    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 4 */
+    {0x3F, 0x42, 0x00, 0x00, 0x00},     /* Sample 5 */
+    {0x3F, 0x41, 0x00, 0x00, 0x00},     /* Sample 6 */
+    {0x30, 0x41, 0x00, 0x00, 0x00},     /* Sample 7 */
+    {0x2A, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
+    {0x29, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
+    {0x28, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
+    {0x27, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
+    {0x26, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
+    {0x25, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
+    {0x24, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
+    {0x4A, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
+    {0x7F, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
+    {0x7F, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
+    {0x5F, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
+    {0x50, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
+    {0x49, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
+    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
+    {0x47, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
+    {0x46, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
+    {0x15}                      /* Output Amplitude */
+};
+
+u_int8_t    TWV_E1_120Ohm[25][5] =      /* E1 120 Ohm */
+{
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 0 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 1 */
+    {0x0A, 0x00, 0x00, 0x00, 0x00},     /* Sample 2 */
+    {0x3F, 0x00, 0x00, 0x00, 0x00},     /* Sample 3 */
+    {0x3F, 0x00, 0x00, 0x00, 0x00},     /* Sample 4 */
+    {0x39, 0x00, 0x00, 0x00, 0x00},     /* Sample 5 */
+    {0x38, 0x00, 0x00, 0x00, 0x00},     /* Sample 6 */
+    {0x36, 0x00, 0x00, 0x00, 0x00},     /* Sample 7 */
+    {0x36, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
+    {0x35, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
+    {0x35, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
+    {0x35, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
+    {0x35, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
+    {0x35, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
+    {0x35, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
+    {0x2D, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
+    {0x0C}                      /* PMC's suggested value */
+/*  { 0x10 }                Output Amplitude */
+};
+
+
+
+u_int8_t    TWV_E1_75Ohm[25][5] =       /* E1 75 Ohm */
+{
+#ifdef PMCC4_DOES_NOT_SUPPORT
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 0 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 1 */
+    {0x0A, 0x00, 0x00, 0x00, 0x00},     /* Sample 2 */
+    {0x28, 0x00, 0x00, 0x00, 0x00},     /* Sample 3 */
+    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 4 */
+    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 5 */
+    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 6 */
+    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 7 */
+    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 8 */
+    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 9 */
+    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 10 */
+    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 11 */
+    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 12 */
+    {0x3A, 0x00, 0x00, 0x00, 0x00},     /* Sample 13 */
+    {0x32, 0x00, 0x00, 0x00, 0x00},     /* Sample 14 */
+    {0x14, 0x00, 0x00, 0x00, 0x00},     /* Sample 15 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 16 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 17 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 18 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 19 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 20 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 21 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 22 */
+    {0x00, 0x00, 0x00, 0x00, 0x00},     /* Sample 23 */
+#endif
+    {0x0C}                      /* Output Amplitude */
+};
+
+
+u_int32_t T1_Equalizer[256] =   /* T1 Receiver Equalizer */
+{
+    0x03FE1840, 0x03F61840, 0x03EE1840, 0x03E61840,     /* 000 - 003 */
+        0x03DE1840, 0x03D61840, 0x03D61840, 0x03D61840, /* 004 - 007 */
+        0x03CE1840, 0x03CE1840, 0x03CE1840, 0x03CE1840, /* 008 - 011 */
+        0x03C61840, 0x03C61840, 0x03C61840, 0x0BBE1840, /* 012 - 015 */
+        0x0BBE1840, 0x0BBE1840, 0x0BBE1840, 0x0BB61840, /* 016 - 019 */
+        0x0BB61840, 0x0BB61840, 0x0BB61840, 0x13AE1838, /* 020 - 023 */
+        0x13AE183C, 0x13AE1840, 0x13AE1840, 0x13AE1840, /* 024 - 027 */
+        0x13AE1840, 0x1BB618B8, 0x1BAE18B8, 0x1BAE18BC, /* 028 - 031 */
+        0x1BAE18C0, 0x1BAE18C0, 0x23A618C0, 0x23A618C0, /* 032 - 035 */
+        0x23A618C0, 0x23A618C0, 0x23A618C0, 0x239E18C0, /* 036 - 039 */
+        0x239E18C0, 0x239E18C0, 0x239E18C0, 0x239E18C0, /* 040 - 043 */
+        0x2B9618C0, 0x2B9618C0, 0x2B9618C0, 0x33961940, /* 044 - 047 */
+        0x37961940, 0x37961940, 0x37961940, 0x3F9E19C0, /* 048 - 051 */
+        0x3F9E19C0, 0x3F9E19C0, 0x3FA61A40, 0x3FA61A40, /* 052 - 055 */
+        0x3FA61A40, 0x3FA61A40, 0x3F9619C0, 0x3F9619C0, /* 056 - 059 */
+        0x3F9619C0, 0x3F9619C0, 0x479E1A40, 0x479E1A40, /* 060 - 063 */
+        0x479E1A40, 0x47961A40, 0x47961A40, 0x47961A40, /* 064 - 067 */
+        0x47961A40, 0x4F8E1A40, 0x4F8E1A40, 0x4F8E1A40, /* 068 - 071 */
+        0x4F8E1A40, 0x4F8E1A40, 0x57861A40, 0x57861A40, /* 072 - 075 */
+        0x57861A40, 0x57861A40, 0x57861A40, 0x5F861AC0, /* 076 - 079 */
+        0x5F861AC0, 0x5F861AC0, 0x5F861AC0, 0x5F861AC0, /* 080 - 083 */
+        0x5F861AC0, 0x5F7E1AC0, 0x5F7E1AC0, 0x5F7E1AC0, /* 084 - 087 */
+        0x5F7E1AC0, 0x5F7E1AC0, 0x677E2AC0, 0x677E2AC0, /* 088 - 091 */
+        0x677E2AC0, 0x677E2AC0, 0x67762AC0, 0x67762AC0, /* 092 - 095 */
+        0x67762AC0, 0x67762AC0, 0x67762AC0, 0x6F6E2AC0, /* 096 - 099 */
+        0x6F6E2AC0, 0x6F6E2AC0, 0x6F6E2AC0, 0x776E3AC0, /* 100 - 103 */
+        0x776E3AC0, 0x776E3AC0, 0x776E3AC0, 0x7F663AC0, /* 104 - 107 */
+        0x7F663AC0, 0x7F664AC0, 0x7F664AC0, 0x7F664AC0, /* 108 - 111 */
+        0x7F664AC0, 0x87665AC0, 0x87665AC0, 0x87665AC0, /* 112 - 115 */
+        0x87665AC0, 0x87665AC0, 0x875E5AC0, 0x875E5AC0, /* 116 - 119 */
+        0x875E5AC0, 0x875E5AC0, 0x875E5AC0, 0x8F5E6AC0, /* 120 - 123 */
+        0x8F5E6AC0, 0x8F5E6AC0, 0x8F5E6AC0, 0x975E7AC0, /* 124 - 127 */
+        0x975E7AC0, 0x975E7AC0, 0x975E7AC0, 0x9F5E8AC0, /* 128 - 131 */
+        0x9F5E8AC0, 0x9F5E8AC0, 0x9F5E8AC0, 0x9F5E8AC0, /* 132 - 135 */
+        0xA7569AC0, 0xA7569AC0, 0xA7569AC0, 0xA7569AC0, /* 136 - 139 */
+        0xA756AAC0, 0xA756AAC0, 0xA756AAC0, 0xAF4EAAC0, /* 140 - 143 */
+        0xAF4EAAC0, 0xAF4EAAC0, 0xAF4EAAC0, 0xAF4EAAC0, /* 144 - 147 */
+        0xB746AAC0, 0xB746AAC0, 0xB746AAC0, 0xB746AAC0, /* 148 - 151 */
+        0xB746AAC0, 0xB746AAC0, 0xB746AAC0, 0xB746BAC0, /* 152 - 155 */
+        0xB746BAC0, 0xB746BAC0, 0xBF4EBB40, 0xBF4EBB40, /* 156 - 159 */
+        0xBF4EBB40, 0xBF4EBB40, 0xBF4EBB40, 0xBF4EBB40, /* 160 - 163 */
+        0xBF4EBB40, 0xBF4EBB40, 0xBF4EBB40, 0xBE46CB40, /* 164 - 167 */
+        0xBE46CB40, 0xBE46CB40, 0xBE46CB40, 0xBE46CB40, /* 168 - 171 */
+        0xBE46CB40, 0xBE46DB40, 0xBE46DB40, 0xBE46DB40, /* 172 - 175 */
+        0xC63ECB40, 0xC63ECB40, 0xC63EDB40, 0xC63EDB40, /* 176 - 179 */
+        0xC63EDB40, 0xC644DB40, 0xC644DB40, 0xC644DB40, /* 180 - 183 */
+        0xC644DB40, 0xC63CDB40, 0xC63CDB40, 0xC63CDB40, /* 184 - 187 */
+        0xC63CDB40, 0xD634DB40, 0xD634DB40, 0xD634DB40, /* 188 - 191 */
+        0xD634DB40, 0xD634DB40, 0xDE2CDB3C, 0xDE2CDB3C, /* 192 - 195 */
+        0xDE2CDB3C, 0xE62CDB40, 0xE62CDB40, 0xE62CDB40, /* 196 - 199 */
+        0xE62CDB40, 0xE62CDB40, 0xE62CEB40, 0xE62CEB40, /* 200 - 203 */
+        0xE62CEB40, 0xEE2CFB40, 0xEE2CFB40, 0xEE2CFB40, /* 204 - 207 */
+        0xEE2D0B40, 0xEE2D0B40, 0xEE2D0B40, 0xEE2D0B40, /* 208 - 211 */
+        0xEE2D0B40, 0xF5250B38, 0xF5250B3C, 0xF5250B40, /* 212 - 215 */
+        0xF5251B40, 0xF5251B40, 0xF5251B40, 0xF5251B40, /* 216 - 219 */
+        0xF5251B40, 0xFD252B40, 0xFD252B40, 0xFD252B40, /* 220 - 223 */
+        0xFD252B40, 0xFD252740, 0xFD252740, 0xFD252740, /* 224 - 227 */
+        0xFD252340, 0xFD252340, 0xFD252340, 0xFD253340, /* 228 - 231 */
+        0xFD253340, 0xFD253340, 0xFD253340, 0xFD253340, /* 232 - 235 */
+        0xFD253340, 0xFD253340, 0xFD253340, 0xFC254340, /* 236 - 239 */
+        0xFD254340, 0xFD254340, 0xFD254344, 0xFC254348, /* 240 - 243 */
+        0xFC25434C, 0xFD2543BC, 0xFD2543C0, 0xFC2543C0, /* 244 - 247 */
+        0xFC2343C0, 0xFC2343C0, 0xFD2343C0, 0xFC2143C0, /* 248 - 251 */
+        0xFC2143C0, 0xFC2153C0, 0xFD2153C0, 0xFC2153C0  /* 252 - 255 */
+};
+
+
+u_int32_t   E1_Equalizer[256] = /* E1 Receiver Equalizer */
+{
+    0x07DE182C, 0x07DE182C, 0x07D6182C, 0x07D6182C,     /* 000 - 003 */
+    0x07D6182C, 0x07CE182C, 0x07CE182C, 0x07CE182C,     /* 004 - 007 */
+    0x07C6182C, 0x07C6182C, 0x07C6182C, 0x07BE182C,     /* 008 - 011 */
+    0x07BE182C, 0x07BE182C, 0x07BE182C, 0x07BE182C,     /* 012 - 015 */
+    0x07B6182C, 0x07B6182C, 0x07B6182C, 0x07B6182C,     /* 016 - 019 */
+    0x07B6182C, 0x07AE182C, 0x07AE182C, 0x07AE182C,     /* 020 - 023 */
+    0x07AE182C, 0x07AE182C, 0x07B618AC, 0x07AE18AC,     /* 024 - 027 */
+    0x07AE18AC, 0x07AE18AC, 0x07AE18AC, 0x07A618AC,     /* 028 - 031 */
+    0x07A618AC, 0x07A618AC, 0x07A618AC, 0x079E18AC,     /* 032 - 035 */
+    0x07A6192C, 0x07A6192C, 0x07A6192C, 0x0FA6192C,     /* 036 - 039 */
+    0x0FA6192C, 0x0F9E192C, 0x0F9E192C, 0x0F9E192C,     /* 040 - 043 */
+    0x179E192C, 0x17A619AC, 0x179E19AC, 0x179E19AC,     /* 044 - 047 */
+    0x179619AC, 0x1F9619AC, 0x1F9619AC, 0x1F8E19AC,     /* 048 - 051 */
+    0x1F8E19AC, 0x1F8E19AC, 0x278E19AC, 0x278E1A2C,     /* 052 - 055 */
+    0x278E1A2C, 0x278E1A2C, 0x278E1A2C, 0x2F861A2C,     /* 056 - 059 */
+    0x2F861A2C, 0x2F861A2C, 0x2F7E1A2C, 0x2F7E1A2C,     /* 060 - 063 */
+    0x2F7E1A2C, 0x377E1A2C, 0x377E1AAC, 0x377E1AAC,     /* 064 - 067 */
+    0x377E1AAC, 0x377E1AAC, 0x3F7E2AAC, 0x3F7E2AAC,     /* 068 - 071 */
+    0x3F762AAC, 0x3F862B2C, 0x3F7E2B2C, 0x477E2B2C,     /* 072 - 075 */
+    0x477E2F2C, 0x477E2F2C, 0x477E2F2C, 0x47762F2C,     /* 076 - 079 */
+    0x4F762F2C, 0x4F762F2C, 0x4F6E2F2C, 0x4F6E2F2C,     /* 080 - 083 */
+    0x4F6E2F2C, 0x576E2F2C, 0x576E2F2C, 0x576E3F2C,     /* 084 - 087 */
+    0x576E3F2C, 0x576E3F2C, 0x5F6E3F2C, 0x5F6E4F2C,     /* 088 - 091 */
+    0x5F6E4F2C, 0x5F6E4F2C, 0x5F664F2C, 0x67664F2C,     /* 092 - 095 */
+    0x67664F2C, 0x675E4F2C, 0x675E4F2C, 0x67664F2C,     /* 096 - 099 */
+    0x67664F2C, 0x67665F2C, 0x6F6E5F2C, 0x6F6E6F2C,     /* 100 - 103 */
+    0x6F6E6F2C, 0x6F6E7F2C, 0x6F6E7F2C, 0x6F6E7F2C,     /* 104 - 107 */
+    0x77667F2C, 0x77667F2C, 0x775E6F2C, 0x775E7F2C,     /* 108 - 111 */
+    0x775E7F2C, 0x7F5E7F2C, 0x7F5E8F2C, 0x7F5E8F2C,     /* 112 - 115 */
+    0x7F5E8F2C, 0x87568F2C, 0x87568F2C, 0x87568F2C,     /* 116 - 119 */
+    0x874E8F2C, 0x874E8F2C, 0x874E8F2C, 0x8F4E9F2C,     /* 120 - 123 */
+    0x8F4E9F2C, 0x8F4EAF2C, 0x8F4EAF2C, 0x8F4EAF2C,     /* 124 - 127 */
+    0x974EAF2C, 0x974EAF2C, 0x974EAB2C, 0x974EAB2C,     /* 128 - 131 */
+    0x974EAB2C, 0x9F4EAB2C, 0x9F4EBB2C, 0x9F4EBB2C,     /* 132 - 135 */
+    0x9F4EBB2C, 0x9F4ECB2C, 0xA74ECB2C, 0xA74ECB2C,     /* 136 - 139 */
+    0xA746CB2C, 0xA746CB2C, 0xA746CB2C, 0xA746DB2C,     /* 140 - 143 */
+    0xAF46DB2C, 0xAF46EB2C, 0xAF46EB2C, 0xAF4EEB2C,     /* 144 - 147 */
+    0xAE4EEB2C, 0xAE4EEB2C, 0xB546FB2C, 0xB554FB2C,     /* 148 - 151 */
+    0xB54CEB2C, 0xB554FB2C, 0xB554FB2C, 0xBD54FB2C,     /* 152 - 155 */
+    0xBD4CFB2C, 0xBD4CFB2C, 0xBD4CFB2C, 0xBD44EB2C,     /* 156 - 159 */
+    0xC544FB2C, 0xC544FB2C, 0xC544FB2C, 0xC5450B2C,     /* 160 - 163 */
+    0xC5450B2C, 0xC5450B2C, 0xCD450B2C, 0xCD450B2C,     /* 164 - 167 */
+    0xCD3D0B2C, 0xCD3D0B2C, 0xCD3D0B2C, 0xD53D0B2C,     /* 168 - 171 */
+    0xD53D0B2C, 0xD53D1B2C, 0xD53D1B2C, 0xD53D1B2C,     /* 172 - 175 */
+    0xDD3D1B2C, 0xDD3D1B2C, 0xDD351B2C, 0xDD351B2C,     /* 176 - 179 */
+    0xDD351B2C, 0xE5351B2C, 0xE5351B2C, 0xE52D1B2C,     /* 180 - 183 */
+    0xE52D1B2C, 0xE52D3B2C, 0xED2D4B2C, 0xED2D1BA8,     /* 184 - 187 */
+    0xED2D1BAC, 0xED2D17AC, 0xED2D17AC, 0xED2D27AC,     /* 188 - 191 */
+    0xF52D27AC, 0xF52D27AC, 0xF52D2BAC, 0xF52D2BAC,     /* 192 - 195 */
+    0xF52D2BAC, 0xFD2D2BAC, 0xFD2B2BAC, 0xFD2B2BAC,     /* 196 - 199 */
+    0xFD2B2BAC, 0xFD2B2BAC, 0xFD232BAC, 0xFD232BAC,     /* 200 - 203 */
+    0xFD232BAC, 0xFD212BAC, 0xFD212BAC, 0xFD292BAC,     /* 204 - 207 */
+    0xFD292BAC, 0xFD2927AC, 0xFD2937AC, 0xFD2923AC,     /* 208 - 211 */
+    0xFD2923AC, 0xFD2923AC, 0xFD2923AC, 0xFD2123AC,     /* 212 - 215 */
+    0xFD2123AC, 0xFD2123AC, 0xFD2133AC, 0xFD2133AC,     /* 216 - 219 */
+    0xFD2133AC, 0xFD2143AC, 0xFD2143AC, 0xFD2143AC,     /* 220 - 223 */
+    0xFC2143AC, 0xFC2143AC, 0xFC1943AC, 0xFC1943AC,     /* 224 - 227 */
+    0xFC1943AC, 0xFC1943AC, 0xFC1953AC, 0xFC1953AC,     /* 228 - 231 */
+    0xFC1953AC, 0xFC1953AC, 0xFC1963AC, 0xFC1963AC,     /* 232 - 235 */
+    0xFC1963AC, 0xFC1973AC, 0xFC1973AC, 0xFC1973AC,     /* 236 - 239 */
+    0xFC1973AC, 0xFC1973AC, 0xFC1983AC, 0xFC1983AC,     /* 240 - 243 */
+    0xFC1983AC, 0xFC1983AC, 0xFC1983AC, 0xFC1993AC,     /* 244 - 247 */
+    0xFC1993AC, 0xFC1993AC, 0xFC19A3AC, 0xFC19A3AC,     /* 248 - 251 */
+    0xFC19B3AC, 0xFC19B3AC, 0xFC19B3AC, 0xFC19B3AC      /* 252 - 255 */
+};
+
+/*** End-of-Files ***/
diff --git a/drivers/staging/cxt1e1/comet_tables.h b/drivers/staging/cxt1e1/comet_tables.h
new file mode 100644 (file)
index 0000000..80424a2
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * $Id: comet_tables.h,v 1.5 2006/01/02 22:37:31 rickd PMCC4_3_1B $
+ */
+
+#ifndef _INC_COMET_TBLS_H_
+#define _INC_COMET_TBLS_H_
+
+/*-----------------------------------------------------------------------------
+ * comet_tables.h - Waveform Tables for the PM4351 'COMET'
+ *
+ * Copyright (C) 2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@sbei.com
+ * SBE, Inc.  San Ramon, California  U.S.A.
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 1.5 $
+ * Last changed on $Date: 2006/01/02 22:37:31 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: comet_tables.h,v $
+ * Revision 1.5  2006/01/02 22:37:31  rickd
+ * Double indexed arrays need sizings to avoid CC errors under
+ * gcc 4.0.0
+ *
+ * Revision 1.4  2005/10/17 23:55:28  rickd
+ * The 75 Ohm transmit waveform is not supported on PMCC4.
+ *
+ * Revision 1.3  2005/09/28 00:10:08  rickd
+ * Add GNU License info. Structures moved to -C- file.
+ *
+ * Revision 1.2  2005/04/28 23:43:04  rickd
+ * Add RCS tracking heading.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+/*****************************************************************************
+*
+*  Array names:
+*
+*       TWVLongHaul0DB
+*       TWVLongHaul7_5DB
+*       TWVLongHaul15DB
+*       TWVLongHaul22_5DB
+*       TWVShortHaul0
+*       TWVShortHaul1
+*       TWVShortHaul2
+*       TWVShortHaul3
+*       TWVShortHaul4
+*       TWVShortHaul5
+*       TWV_E1_120Ohm
+*       TWV_E1_75Ohm    <not supported>
+*       T1_Equalizer
+*       E1_Equalizer
+*
+*****************************************************************************/
+
+extern u_int8_t TWVLongHaul0DB[25][5];      /* T1 Long Haul 0 DB */
+extern u_int8_t TWVLongHaul7_5DB[25][5];    /* T1 Long Haul 7.5 DB */
+extern u_int8_t TWVLongHaul15DB[25][5];     /* T1 Long Haul 15 DB */
+extern u_int8_t TWVLongHaul22_5DB[25][5];   /* T1 Long Haul 22.5 DB */
+extern u_int8_t TWVShortHaul0[25][5];       /* T1 Short Haul 0-110 ft */
+extern u_int8_t TWVShortHaul1[25][5];       /* T1 Short Haul 110-220 ft */
+extern u_int8_t TWVShortHaul2[25][5];       /* T1 Short Haul 220-330 ft */
+extern u_int8_t TWVShortHaul3[25][5];       /* T1 Short Haul 330-440 ft */
+extern u_int8_t TWVShortHaul4[25][5];       /* T1 Short Haul 440-550 ft */
+extern u_int8_t TWVShortHaul5[25][5];       /* T1 Short Haul 550-660 ft */
+extern u_int8_t TWV_E1_75Ohm[25][5];        /* E1 75 Ohm */
+extern u_int8_t TWV_E1_120Ohm[25][5];       /* E1 120 Ohm */
+extern u_int32_t T1_Equalizer[256];    /* T1 Receiver Equalizer */
+extern u_int32_t E1_Equalizer[256];    /* E1 Receiver Equalizer */
+
+#endif                          /* _INC_COMET_TBLS_H_ */
diff --git a/drivers/staging/cxt1e1/functions.c b/drivers/staging/cxt1e1/functions.c
new file mode 100644 (file)
index 0000000..c95c62d
--- /dev/null
@@ -0,0 +1,366 @@
+/* Copyright (C) 2003-2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/hdlc.h>
+#include "pmcc4_sysdep.h"
+#include "sbecom_inline_linux.h"
+#include "libsbew.h"
+#include "pmcc4.h"
+
+
+#ifdef SBE_INCLUDE_SYMBOLS
+#define STATIC
+#else
+#define STATIC  static
+#endif
+
+#if defined(CONFIG_SBE_HDLC_V7) || defined(CONFIG_SBE_WAN256T3_HDLC_V7) || \
+    defined(CONFIG_SBE_HDLC_V7_MODULE) || defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
+#define _v7_hdlc_  1
+#else
+#define _v7_hdlc_  0
+#endif
+
+#if _v7_hdlc_
+#define V7(x) (x ## _v7)
+extern int  hdlc_netif_rx_v7 (hdlc_device *, struct sk_buff *);
+extern int  register_hdlc_device_v7 (hdlc_device *);
+extern int  unregister_hdlc_device_v7 (hdlc_device *);
+
+#else
+#define V7(x) x
+#endif
+
+
+#ifndef USE_MAX_INT_DELAY
+static int  dummy = 0;
+
+#endif
+
+extern int  log_level;
+extern int  drvr_state;
+
+
+#if 1
+u_int32_t
+pci_read_32 (u_int32_t *p)
+{
+#ifdef FLOW_DEBUG
+    u_int32_t   v;
+
+    FLUSH_PCI_READ ();
+    v = le32_to_cpu (*p);
+    if (log_level >= LOG_DEBUG)
+        printk ("pci_read : %x = %x\n", (u_int32_t) p, v);
+    return v;
+#else
+    FLUSH_PCI_READ ();              /* */
+    return le32_to_cpu (*p);
+#endif
+}
+
+void
+pci_write_32 (u_int32_t *p, u_int32_t v)
+{
+#ifdef FLOW_DEBUG
+    if (log_level >= LOG_DEBUG)
+        printk ("pci_write: %x = %x\n", (u_int32_t) p, v);
+#endif
+    *p = cpu_to_le32 (v);
+    FLUSH_PCI_WRITE ();             /* This routine is called from routines
+                                     * which do multiple register writes
+                                     * which themselves need flushing between
+                                     * writes in order to guarantee write
+                                     * ordering.  It is less code-cumbersome
+                                     * to flush here-in then to investigate
+                                     * and code the many other register
+                                     * writing routines. */
+}
+#endif
+
+
+void
+pci_flush_write (ci_t * ci)
+{
+    volatile u_int32_t v;
+
+    /* issue a PCI read to flush PCI write thru bridge */
+    v = *(u_int32_t *) &ci->reg->glcd;  /* any address would do */
+
+    /*
+     * return nothing, this just reads PCI bridge interface to flush
+     * previously written data
+     */
+}
+
+
+STATIC void
+watchdog_func (unsigned long arg)
+{
+    struct watchdog *wd = (void *) arg;
+
+    if (drvr_state != SBE_DRVR_AVAILABLE)
+    {
+        if (log_level >= LOG_MONITOR)
+            printk (KERN_WARNING "watchdog_func: drvr not available (%x)\n", drvr_state);
+        return;
+    }
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+    /* Initialize the tq entry only the first time */
+    if (wd->init_tq)
+    {
+        wd->init_tq = 0;
+        wd->tq.routine = wd->func;
+        wd->tq.sync = 0;
+        wd->tq.data = wd->softc;
+    }
+    schedule_task (&wd->tq);
+#else
+    schedule_work (&wd->work);
+#endif
+    mod_timer (&wd->h, jiffies + wd->ticks);
+}
+
+int OS_init_watchdog(struct watchdog *wdp, void (*f) (void *), void *c, int usec)
+{
+    wdp->func = f;
+    wdp->softc = c;
+    wdp->ticks = (HZ) * (usec / 1000) / 1000;
+    INIT_WORK(&wdp->work, (void *)f);
+    init_timer (&wdp->h);
+    {
+        ci_t       *ci = (ci_t *) c;
+
+        wdp->h.data = (unsigned long) &ci->wd;
+    }
+    wdp->h.function = watchdog_func;
+    return 0;
+}
+
+void
+OS_uwait (int usec, char *description)
+{
+    int         tmp;
+
+    if (usec >= 1000)
+    {
+        mdelay (usec / 1000);
+        /* now delay residual */
+        tmp = (usec / 1000) * 1000; /* round */
+        tmp = usec - tmp;           /* residual */
+        if (tmp)
+        {                           /* wait on residual */
+            udelay (tmp);
+        }
+    } else
+    {
+        udelay (usec);
+    }
+}
+
+/* dummy short delay routine called as a subroutine so that compiler
+ * does not optimize/remove its intent (a short delay)
+ */
+
+void
+OS_uwait_dummy (void)
+{
+#ifndef USE_MAX_INT_DELAY
+    dummy++;
+#else
+    udelay (1);
+#endif
+}
+
+
+void
+OS_sem_init (void *sem, int state)
+{
+    switch (state)
+    {
+        case SEM_TAKEN:
+        init_MUTEX_LOCKED ((struct semaphore *) sem);
+        break;
+    case SEM_AVAILABLE:
+        init_MUTEX ((struct semaphore *) sem);
+        break;
+    default:                        /* otherwise, set sem.count to state's
+                                     * value */
+        sema_init (sem, state);
+        break;
+    }
+}
+
+
+int
+sd_line_is_ok (void *user)
+{
+    struct net_device *ndev = (struct net_device *) user;
+
+    return (netif_carrier_ok (ndev));
+}
+
+void
+sd_line_is_up (void *user)
+{
+    struct net_device *ndev = (struct net_device *) user;
+
+    netif_carrier_on (ndev);
+    return;
+}
+
+void
+sd_line_is_down (void *user)
+{
+    struct net_device *ndev = (struct net_device *) user;
+
+    netif_carrier_off (ndev);
+    return;
+}
+
+void
+sd_disable_xmit (void *user)
+{
+    struct net_device *dev = (struct net_device *) user;
+
+    netif_stop_queue (dev);
+    return;
+}
+
+void
+sd_enable_xmit (void *user)
+{
+    struct net_device *dev = (struct net_device *) user;
+
+    netif_wake_queue (dev);
+    return;
+}
+
+int
+sd_queue_stopped (void *user)
+{
+    struct net_device *ndev = (struct net_device *) user;
+
+    return (netif_queue_stopped (ndev));
+}
+
+void sd_recv_consume(void *token, size_t len, void *user)
+{
+    struct net_device *ndev = user;
+    struct sk_buff *skb = token;
+
+    skb->dev = ndev;
+    skb_put (skb, len);
+    skb->protocol = hdlc_type_trans(skb, ndev);
+    netif_rx(skb);
+}
+
+
+/**
+ ** Read some reserved location w/in the COMET chip as a usable
+ ** VMETRO trigger point or other trace marking event.
+ **/
+
+#include "comet.h"
+
+extern ci_t *CI;                /* dummy pointer to board ZERO's data */
+void
+VMETRO_TRACE (void *x)
+{
+    u_int32_t   y = (u_int32_t) x;
+
+    pci_write_32 ((u_int32_t *) &CI->cpldbase->leds, y);
+}
+
+
+void
+VMETRO_TRIGGER (ci_t * ci, int x)
+{
+    comet_t    *comet;
+    volatile u_int32_t data;
+
+    comet = ci->port[0].cometbase;  /* default to COMET # 0 */
+
+    switch (x)
+    {
+    default:
+    case 0:
+        data = pci_read_32 ((u_int32_t *) &comet->__res24);     /* 0x90 */
+        break;
+    case 1:
+        data = pci_read_32 ((u_int32_t *) &comet->__res25);     /* 0x94 */
+        break;
+    case 2:
+        data = pci_read_32 ((u_int32_t *) &comet->__res26);     /* 0x98 */
+        break;
+    case 3:
+        data = pci_read_32 ((u_int32_t *) &comet->__res27);     /* 0x9C */
+        break;
+    case 4:
+        data = pci_read_32 ((u_int32_t *) &comet->__res88);     /* 0x220 */
+        break;
+    case 5:
+        data = pci_read_32 ((u_int32_t *) &comet->__res89);     /* 0x224 */
+        break;
+    case 6:
+        data = pci_read_32 ((u_int32_t *) &comet->__res8A);     /* 0x228 */
+        break;
+    case 7:
+        data = pci_read_32 ((u_int32_t *) &comet->__res8B);     /* 0x22C */
+        break;
+    case 8:
+        data = pci_read_32 ((u_int32_t *) &comet->__resA0);     /* 0x280 */
+        break;
+    case 9:
+        data = pci_read_32 ((u_int32_t *) &comet->__resA1);     /* 0x284 */
+        break;
+    case 10:
+        data = pci_read_32 ((u_int32_t *) &comet->__resA2);     /* 0x288 */
+        break;
+    case 11:
+        data = pci_read_32 ((u_int32_t *) &comet->__resA3);     /* 0x28C */
+        break;
+    case 12:
+        data = pci_read_32 ((u_int32_t *) &comet->__resA4);     /* 0x290 */
+        break;
+    case 13:
+        data = pci_read_32 ((u_int32_t *) &comet->__resA5);     /* 0x294 */
+        break;
+    case 14:
+        data = pci_read_32 ((u_int32_t *) &comet->__resA6);     /* 0x298 */
+        break;
+    case 15:
+        data = pci_read_32 ((u_int32_t *) &comet->__resA7);     /* 0x29C */
+        break;
+    case 16:
+        data = pci_read_32 ((u_int32_t *) &comet->__res74);     /* 0x1D0 */
+        break;
+    case 17:
+        data = pci_read_32 ((u_int32_t *) &comet->__res75);     /* 0x1D4 */
+        break;
+    case 18:
+        data = pci_read_32 ((u_int32_t *) &comet->__res76);     /* 0x1D8 */
+        break;
+    case 19:
+        data = pci_read_32 ((u_int32_t *) &comet->__res77);     /* 0x1DC */
+        break;
+    }
+}
+
+
+/***  End-of-File  ***/
diff --git a/drivers/staging/cxt1e1/hwprobe.c b/drivers/staging/cxt1e1/hwprobe.c
new file mode 100644 (file)
index 0000000..0f9d653
--- /dev/null
@@ -0,0 +1,400 @@
+/* Copyright (C) 2007  One Stop Systems
+ * Copyright (C) 2003-2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/hdlc.h>
+#include <linux/if_arp.h>
+#include <asm/uaccess.h>
+#include <linux/rtnetlink.h>
+#include <linux/pci.h>
+#include "pmcc4_sysdep.h"
+#include "sbecom_inline_linux.h"
+#include "libsbew.h"
+#include "pmcc4_private.h"
+#include "pmcc4.h"
+#include "pmcc4_ioctls.h"
+#include "pmc93x6_eeprom.h"
+#ifdef CONFIG_PROC_FS
+#include "sbeproc.h"
+#endif
+
+#ifdef SBE_INCLUDE_SYMBOLS
+#define STATIC
+#else
+#define STATIC  static
+#endif
+
+extern int  log_level;
+extern int  error_flag;
+extern int  drvr_state;
+
+/* forward references */
+void        c4_stopwd (ci_t *);
+struct net_device * __init c4_add_dev (hdw_info_t *, int, unsigned long, unsigned long, int, int);
+
+
+struct s_hdw_info hdw_info[MAX_BOARDS];
+
+
+void        __init
+show_two (hdw_info_t * hi, int brdno)
+{
+    ci_t       *ci;
+    struct pci_dev *pdev;
+    char       *bid;
+    char       *bp, banner[80];
+    char        sn[6];
+
+    bp = banner;
+    memset (banner, 0, 80);         /* clear print buffer */
+
+    ci = (ci_t *)(netdev_priv(hi->ndev));
+    bid = sbeid_get_bdname (ci);
+    switch (hi->promfmt)
+    {
+    case PROM_FORMAT_TYPE1:
+        memcpy (sn, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
+        break;
+    case PROM_FORMAT_TYPE2:
+        memcpy (sn, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
+        break;
+    default:
+        memset (sn, 0, 6);
+        break;
+    }
+
+    sprintf (banner, "%s: %s  S/N %06X, MUSYCC Rev %02X",
+             hi->devname, bid,
+             ((sn[3] << 16) & 0xff0000) |
+              ((sn[4] << 8) & 0x00ff00) |
+              (sn[5] & 0x0000ff),
+             (u_int8_t) hi->revid[0]);
+
+    printk ("%s\n", banner);
+
+    pdev = hi->pdev[0];
+    printk ("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
+            hi->devname, "MUSYCC",
+            (unsigned long) hi->addr_mapped[0], hi->addr[0],
+            hi->pci_busno, (u_int8_t) PCI_SLOT (pdev->devfn),
+            (u_int8_t) PCI_FUNC (pdev->devfn), pdev->irq);
+
+    pdev = hi->pdev[1];
+    printk ("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
+            hi->devname, "EBUS  ",
+            (unsigned long) hi->addr_mapped[1], hi->addr[1],
+            hi->pci_busno, (u_int8_t) PCI_SLOT (pdev->devfn),
+            (u_int8_t) PCI_FUNC (pdev->devfn), pdev->irq);
+}
+
+
+void        __init
+hdw_sn_get (hdw_info_t * hi, int brdno)
+{
+    /* obtain hardware EEPROM information */
+    long        addr;
+
+    addr = (long) hi->addr_mapped[1] + EEPROM_OFFSET;
+
+    /* read EEPROM with largest known format size... */
+    pmc_eeprom_read_buffer (addr, 0, (char *) hi->mfg_info.data, sizeof (FLD_TYPE2));
+
+#if 0
+    {
+        unsigned char *ucp = (unsigned char *) &hi->mfg_info.data;
+
+        printk ("eeprom[00]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                *(ucp + 0), *(ucp + 1), *(ucp + 2), *(ucp + 3), *(ucp + 4), *(ucp + 5), *(ucp + 6), *(ucp + 7));
+        printk ("eeprom[08]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                *(ucp + 8), *(ucp + 9), *(ucp + 10), *(ucp + 11), *(ucp + 12), *(ucp + 13), *(ucp + 14), *(ucp + 15));
+        printk ("eeprom[16]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                *(ucp + 16), *(ucp + 17), *(ucp + 18), *(ucp + 19), *(ucp + 20), *(ucp + 21), *(ucp + 22), *(ucp + 23));
+        printk ("eeprom[24]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                *(ucp + 24), *(ucp + 25), *(ucp + 26), *(ucp + 27), *(ucp + 28), *(ucp + 29), *(ucp + 30), *(ucp + 31));
+        printk ("eeprom[32]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                *(ucp + 32), *(ucp + 33), *(ucp + 34), *(ucp + 35), *(ucp + 36), *(ucp + 37), *(ucp + 38), *(ucp + 39));
+        printk ("eeprom[40]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                *(ucp + 40), *(ucp + 41), *(ucp + 42), *(ucp + 43), *(ucp + 44), *(ucp + 45), *(ucp + 46), *(ucp + 47));
+    }
+#endif
+#if 0
+    printk ("sn: %x %x %x %x %x %x\n",
+            hi->mfg_info.Serial[0],
+            hi->mfg_info.Serial[1],
+            hi->mfg_info.Serial[2],
+            hi->mfg_info.Serial[3],
+            hi->mfg_info.Serial[4],
+            hi->mfg_info.Serial[5]);
+#endif
+
+    if ((hi->promfmt = pmc_verify_cksum (&hi->mfg_info.data)) == PROM_FORMAT_Unk)
+    {
+        /* bad crc, data is suspect */
+        if (log_level >= LOG_WARN)
+            printk ("%s: EEPROM cksum error\n", hi->devname);
+        hi->mfg_info_sts = EEPROM_CRCERR;
+    } else
+        hi->mfg_info_sts = EEPROM_OK;
+}
+
+
+void        __init
+prep_hdw_info (void)
+{
+    hdw_info_t *hi;
+    int         i;
+
+    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+    {
+        hi->pci_busno = 0xff;
+        hi->pci_slot = 0xff;
+        hi->pci_pin[0] = 0;
+        hi->pci_pin[1] = 0;
+        hi->ndev = 0;
+        hi->addr[0] = 0L;
+        hi->addr[1] = 0L;
+        hi->addr_mapped[0] = 0L;
+        hi->addr_mapped[1] = 0L;
+    }
+}
+
+void
+cleanup_ioremap (void)
+{
+    hdw_info_t *hi;
+    int         i;
+
+    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+    {
+        if (hi->pci_slot == 0xff)
+            break;
+        if (hi->addr_mapped[0])
+        {
+            iounmap ((void *) (hi->addr_mapped[0]));
+            release_mem_region ((long) hi->addr[0], hi->len[0]);
+            hi->addr_mapped[0] = 0;
+        }
+        if (hi->addr_mapped[1])
+        {
+            iounmap ((void *) (hi->addr_mapped[1]));
+            release_mem_region ((long) hi->addr[1], hi->len[1]);
+            hi->addr_mapped[1] = 0;
+        }
+    }
+}
+
+
+void
+cleanup_devs (void)
+{
+    hdw_info_t *hi;
+    int         i;
+
+    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+    {
+        if (hi->pci_slot == 0xff || !hi->ndev)
+            break;
+        c4_stopwd(netdev_priv(hi->ndev));
+#ifdef CONFIG_PROC_FS
+        sbecom_proc_brd_cleanup(netdev_priv(hi->ndev));
+#endif
+        unregister_netdev (hi->ndev);
+        free_irq (hi->pdev[0]->irq, hi->ndev);
+#ifdef CONFIG_SBE_PMCC4_NCOMM
+        free_irq (hi->pdev[1]->irq, hi->ndev);
+#endif
+        OS_kfree (hi->ndev);
+    }
+}
+
+
+STATIC int  __init
+c4_hdw_init (struct pci_dev * pdev, int found)
+{
+    hdw_info_t *hi;
+    int         i;
+    int         fun, slot;
+    unsigned char busno = 0xff;
+
+    /* our MUSYCC chip supports two functions, 0 & 1 */
+    if ((fun = PCI_FUNC (pdev->devfn)) > 1)
+    {
+        printk (KERN_WARNING "%s: unexpected devfun: 0x%x\n", THIS_MODULE->name, pdev->devfn);
+        return 0;
+    }
+    if (pdev->bus)                  /* obtain bus number */
+        busno = pdev->bus->number;
+    else
+        busno = 0;                  /* default for system PCI inconsistency */
+    slot = pdev->devfn & ~0x07;
+
+    /*
+     * Functions 0 & 1 for a given board (identified by same bus(busno) and
+     * slot(slot)) are placed into the same 'hardware' structure.  The first
+     * part of the board's functionality will be placed into an unpopulated
+     * element, identified by "slot==(0xff)".  The second part of a board's
+     * functionality will match the previously loaded slot/busno.
+     */
+    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+    {
+        /*
+         * match with board's first found interface, otherwise this is first
+         * found
+         */
+        if ((hi->pci_slot == 0xff) ||   /* new board */
+            ((hi->pci_slot == slot) && (hi->bus == pdev->bus)))
+            break;                  /* found for-loop exit */
+    }
+    if (i == MAX_BOARDS)            /* no match in above loop means MAX
+                                     * exceeded */
+    {
+        printk (KERN_WARNING "%s: exceeded number of allowed devices (>%d)?\n",
+                THIS_MODULE->name, MAX_BOARDS);
+        return 0;
+    }
+    if (pdev->bus)
+        hi->pci_busno = pdev->bus->number;
+    else
+        hi->pci_busno = 0;          /* default for system PCI inconsistency */
+    hi->pci_slot = slot;
+    pci_read_config_byte (pdev, PCI_INTERRUPT_PIN, &hi->pci_pin[fun]);
+    pci_read_config_byte (pdev, PCI_REVISION_ID, &hi->revid[fun]);
+    hi->bus = pdev->bus;
+    hi->addr[fun] = pci_resource_start (pdev, 0);
+    hi->len[fun] = pci_resource_end (pdev, 0) - hi->addr[fun] + 1;
+    hi->pdev[fun] = pdev;
+
+    {
+        /*
+         * create device name from module name, plus add the appropriate
+         * board number
+         */
+        char       *cp = hi->devname;
+
+        strcpy (cp, THIS_MODULE->name);
+        cp += strlen (cp);          /* reposition */
+        *cp++ = '-';
+        *cp++ = '0' + (found / 2);  /* there are two found interfaces per
+                                     * board */
+        *cp = 0;                    /* termination */
+    }
+
+    return 1;
+}
+
+
+status_t    __init
+c4hw_attach_all (void)
+{
+    hdw_info_t *hi;
+    struct pci_dev *pdev = NULL;
+    int         found = 0, i, j;
+
+    error_flag = 0;
+    prep_hdw_info ();
+    /*** scan PCI bus for all possible boards */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    while ((pdev = pci_get_device (PCI_VENDOR_ID_CONEXANT,
+                                   PCI_DEVICE_ID_CN8474,
+                                   pdev)))
+#else
+    while ((pdev = pci_find_device (PCI_VENDOR_ID_CONEXANT,
+                                    PCI_DEVICE_ID_CN8474,
+                                    pdev)))
+#endif
+    {
+        if (c4_hdw_init (pdev, found))
+            found++;
+    }
+    if (!found)
+    {
+        printk (KERN_WARNING "%s: No boards found.\n", THIS_MODULE->name);
+        return ENODEV;
+    }
+    /* sanity check for consistant hardware found */
+    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+    {
+        if (hi->pci_slot != 0xff && (!hi->addr[0] || !hi->addr[1]))
+        {
+            printk (KERN_WARNING "%s: something very wrong with pci_get_device.\n", hi->devname);
+            return EIO;
+        }
+    }
+    /* bring board's memory regions on/line */
+    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+    {
+        if (hi->pci_slot == 0xff)
+            break;
+        for (j = 0; j < 2; j++)
+        {
+            if (request_mem_region (hi->addr[j], hi->len[j], hi->devname) == 0)
+            {
+                printk (KERN_WARNING "%s: memory in use, addr=0x%lx, len=0x%lx ?\n",
+                        hi->devname, hi->addr[j], hi->len[j]);
+                cleanup_ioremap ();
+                return ENOMEM;
+            }
+            hi->addr_mapped[j] = (unsigned long) ioremap (hi->addr[j], hi->len[j]);
+            if (!hi->addr_mapped[j])
+            {
+                printk (KERN_WARNING "%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n",
+                        hi->devname, hi->addr[j], hi->len[j]);
+                cleanup_ioremap ();
+                return ENOMEM;
+            }
+#ifdef SBE_MAP_DEBUG
+            printk (KERN_WARNING "%s: io remapped from phys %x to virt %x\n",
+                    hi->devname, (u_int32_t) hi->addr[j], (u_int32_t) hi->addr_mapped[j]);
+#endif
+        }
+    }
+
+    drvr_state = SBE_DRVR_AVAILABLE;
+
+    /* Have now memory mapped all boards.  Now allow board's access to system */
+    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+    {
+        if (hi->pci_slot == 0xff)
+            break;
+        if (pci_enable_device (hi->pdev[0]) ||
+            pci_enable_device (hi->pdev[1]))
+        {
+            drvr_state = SBE_DRVR_DOWN;
+            printk (KERN_WARNING "%s: failed to enable card %d slot %d\n",
+                    hi->devname, i, hi->pci_slot);
+            cleanup_devs ();
+            cleanup_ioremap ();
+            return EIO;
+        }
+        pci_set_master (hi->pdev[0]);
+        pci_set_master (hi->pdev[1]);
+        if (!(hi->ndev = c4_add_dev (hi, i, (long) hi->addr_mapped[0],
+                                     (long) hi->addr_mapped[1],
+                                     hi->pdev[0]->irq,
+                                     hi->pdev[1]->irq)))
+        {
+            drvr_state = SBE_DRVR_DOWN;
+            cleanup_ioremap ();
+            /* NOTE: c4_add_dev() does its own device cleanup */
+#if 0
+            cleanup_devs ();
+#endif
+            return error_flag;      /* error_flag set w/in add_dev() */
+        }
+        show_two (hi, i);           /* displays found information */
+    }
+    return 0;
+}
+
+/***  End-of-File  ***/
diff --git a/drivers/staging/cxt1e1/libsbew.h b/drivers/staging/cxt1e1/libsbew.h
new file mode 100644 (file)
index 0000000..5c99646
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * $Id: libsbew.h,v 2.1 2005/10/27 18:54:19 rickd PMCC4_3_1B $
+ */
+
+#ifndef _INC_LIBSBEW_H_
+#define _INC_LIBSBEW_H_
+
+/*-----------------------------------------------------------------------------
+ * libsbew.h - common library elements, charge across mulitple boards
+ *
+ *   This file contains common Ioctl structures and contents definitions.
+ *
+ * Copyright (C) 2004-2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@sbei.com
+ * SBE, Inc.  San Ramon, California  U.S.A.
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 2.1 $
+ * Last changed on $Date: 2005/10/27 18:54:19 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: libsbew.h,v $
+ * Revision 2.1  2005/10/27 18:54:19  rickd
+ * Add E1PLAIN support.
+ *
+ * Revision 2.0  2005/09/28 00:10:08  rickd
+ * Customized for PMCC4 comet-per-port design.
+ *
+ * Revision 1.15  2005/03/29 00:51:31  rickd
+ * File imported from C1T3 port, Revision 1.15
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef __KERNEL__
+#include <sys/types.h>
+#endif
+
+#ifdef __cplusplus
+extern      "C"
+{
+#endif
+
+/********************************/
+/**  set driver logging level  **/
+/********************************/
+
+/* routine/ioctl: wancfg_set_loglevel() - SBE_IOC_SET_LOGLEVEL */
+
+#define LOG_NONE          0
+#define LOG_ERROR         1
+#define LOG_SBEBUG3       3     /* hidden, for development/debug usage */
+#define LOG_LSCHANGE      5     /* line state change logging */
+#define LOG_LSIMMEDIATE   6     /* line state change logging w/o hysterisis */
+#define LOG_WARN          8
+#define LOG_MONITOR      10
+#define LOG_SBEBUG12     12     /* hidden, for development/debug usage */
+#define LOG_MONITOR2     14     /* hidden, for development/debug usage */
+#define LOG_DEBUG        16
+
+    /* TEMPORARY DEFINES *//* RLD DEBUG */
+#define c4_LOG_NONE      LOG_NONE
+#define c4_LOG_ERROR     LOG_ERROR
+#define c4_LOG_WARN      LOG_WARN
+#define c4_LOG_sTrace    LOG_MONITOR    /* do some trace logging into
+                                         * functions */
+#define c4_LOG_DEBUG     LOG_DEBUG
+#define c4_LOG_MAX       LOG_DEBUG
+
+
+
+/******************************/
+/**  get driver information  **/
+/******************************/
+
+/* routine/ioctl: wancfg_get_drvinfo() - SBE_IOC_GET_DRVINFO */
+
+#define REL_STRLEN   80
+    struct sbe_drv_info
+    {
+        int         rel_strlen;
+        char        release[REL_STRLEN];
+    };
+
+
+/*****************************/
+/**  get board information  **/
+/*****************************/
+
+/* routine/ioctl: wancfg_get_brdinfo() - SBE_IOC_GET_BRDINFO */
+
+#define CHNM_STRLEN   16
+    struct sbe_brd_info
+    {
+        u_int32_t brd_id;       /* SBE's unique PCI VENDOR/DEVID */
+        u_int32_t   brd_sn;
+        int         brd_chan_cnt;       /* number of channels being used */
+        int         brd_port_cnt;       /* number of ports being used */
+        unsigned char brdno;    /* our board number */
+        unsigned char brd_pci_speed;    /* PCI speed, 33/66Mhz */
+                    u_int8_t brd_mac_addr[6];
+        char        first_iname[CHNM_STRLEN];   /* first assigned channel's
+                                                 * interface name */
+        char        last_iname[CHNM_STRLEN];    /* last assigned channel's
+                                                 * interface name */
+        u_int8_t    brd_hdw_id; /* on/board unique hdw ID */
+        u_int8_t    reserved8[3];       /* alignment preservation */
+        u_int32_t   reserved32[3];      /* size preservation */
+    };
+
+/* These IDs are sometimes available thru pci_ids.h, but not currently. */
+
+#define PCI_VENDOR_ID_SBE              0x1176
+#define PCI_DEVICE_ID_WANPMC_C4T1E1    0x0701   /* BID 0x0X, BTYP 0x0X */
+#define PCI_DEVICE_ID_WANPTMC_C4T1E1   0x0702   /* BID 0x41 */
+#define PCI_DEVICE_ID_WANADAPT_HC4T1E1 0x0703   /* BID 0x44 */
+#define PCI_DEVICE_ID_WANPTMC_256T3_T1 0x0704   /* BID 0x42 (T1 Version) */
+#define PCI_DEVICE_ID_WANPCI_C4T1E1    0x0705   /* BID 0x1X, BTYP 0x0X */
+#define PCI_DEVICE_ID_WANPMC_C1T3      0x0706   /* BID 0x45 */
+#define PCI_DEVICE_ID_WANPCI_C2T1E1    0x0707   /* BID 0x1X, BTYP 0x2X */
+#define PCI_DEVICE_ID_WANPCI_C1T1E1    0x0708   /* BID 0x1X, BTYP 0x1X */
+#define PCI_DEVICE_ID_WANPMC_C2T1E1    0x0709   /* BID 0x0X, BTYP 0x2X */
+#define PCI_DEVICE_ID_WANPMC_C1T1E1    0x070A   /* BID 0x0X, BTYP 0x1X */
+#define PCI_DEVICE_ID_WANPTMC_256T3_E1 0x070B   /* BID 0x46 (E1 Version) */
+#define PCI_DEVICE_ID_WANPTMC_C24TE1   0x070C   /* BID 0x47 */
+#define PCI_DEVICE_ID_WANPMC_C4T1E1_L  0x070D   /* BID 0x2X, BTYPE 0x0X w/FP
+                                                 * LEDs */
+#define PCI_DEVICE_ID_WANPMC_C2T1E1_L  0x070E   /* BID 0x2X, BTYPE 0x2X w/FP
+                                                 * LEDs */
+#define PCI_DEVICE_ID_WANPMC_C1T1E1_L  0x070F   /* BID 0x2X, BTYPE 0x1X w/FP
+                                                 * LEDs */
+#define PCI_DEVICE_ID_WANPMC_2SSI      0x0801
+#define PCI_DEVICE_ID_WANPCI_4SSI      0x0802
+#define PCI_DEVICE_ID_WANPMC_2T3E3     0x0900   /* BID 0x43 */
+#define SBE_BOARD_ID(v,id)           ((v<<16) | id)
+
+#define BINFO_PCI_SPEED_unk     0
+#define BINFO_PCI_SPEED_33      1
+#define BINFO_PCI_SPEED_66      2
+
+/***************************/
+/**  obtain interface ID  **/
+/***************************/
+
+/* routine/ioctl: wancfg_get_iid() - SBE_IOC_IID_GET */
+
+    struct sbe_iid_info
+    {
+        u_int32_t   channum;    /* channel requested */
+        char        iname[CHNM_STRLEN]; /* channel's interface name */
+    };
+
+/**************************************/
+/**  get board address information  **/
+/**************************************/
+
+/* routine/ioctl: wancfg_get_brdaddr() - SBE_IOC_BRDADDR_GET */
+
+    struct sbe_brd_addr
+    {
+        unsigned char func;     /* select PCI address space function */
+        unsigned char brdno;    /* returns brdno requested */
+        unsigned char irq;
+        unsigned char size;     /* returns size of address */
+#define BRDADDR_SIZE_64  1
+#define BRDADDR_SIZE_32  2
+        int         reserved1;  /* mod64 align, reserved for future use */
+
+        union
+        {
+            unsigned long virt64;       /* virtual/mapped address */
+            u_int32_t   virt32[2];
+        }           v;
+        union
+        {
+            unsigned long phys64;       /* physical bus address */
+            u_int32_t   phys32[2];
+        }           p;
+        int         reserved2[4];       /* reserved for future use */
+    };
+
+/**********************************/
+/**  read/write board registers  **/
+/**********************************/
+
+/* routine/ioctl: wancfg_read_vec() - SBE_IOC_READ_VEC */
+/* routine/ioctl: wancfg_write_vec() - SBE_IOC_WRITE_VEC */
+
+    struct sbecom_wrt_vec
+    {
+        u_int32_t   reg;
+        u_int32_t   data;
+    };
+
+#define C1T3_CHIP_MSCC_32        0x01000000
+#define C1T3_CHIP_TECT3_8        0x02000000
+#define C1T3_CHIP_CPLD_8         0x03000000
+#define C1T3_CHIP_EEPROM_8       0x04000000
+
+#define W256T3_CHIP_MUSYCC_32    0x02000000
+#define W256T3_CHIP_TEMUX_8      0x10000000
+#define W256T3_CHIP_T8110_8      0x20000000
+#define W256T3_CHIP_T8110_32     0x22000000
+#define W256T3_CHIP_CPLD_8       0x30000000
+#define W256T3_CHIP_EEPROM_8     0x40000000
+
+
+/**********************************/
+/**  read write port parameters  **/
+/**********************************/
+
+/* routine/ioctl: wancfg_getset_port_param() - SBE_IOC_PORT_GET */
+/* routine/ioctl: wancfg_set_port_param() - SBE_IOC_PORT_SET */
+
+/* NOTE: this structure supports hardware which supports individual per/port control */
+
+struct sbecom_port_param
+{
+    u_int8_t    portnum;
+    u_int8_t    port_mode;           /* variations of T1 or E1 mode */
+    u_int8_t    portStatus;
+    u_int8_t    portP;          /* more port parameters (clock source - 0x80;
+                                 * and LBO - 0xf; */
+                                /* bits 0x70 are reserved for future use ) */
+#ifdef SBE_PMCC4_ENABLE
+       u_int32_t   hypersize;  /* RLD DEBUG - add this in until I learn how to make this entry obsolete */
+#endif
+    int         reserved[3-1];    /* reserved for future use */
+    int    _res[4];
+};
+
+#define CFG_CLK_PORT_MASK      0x80     /* Loop timing */
+#define CFG_CLK_PORT_INTERNAL  0x80     /* Loop timing */
+#define CFG_CLK_PORT_EXTERNAL  0x00     /* Loop timing */
+
+#define CFG_LBO_MASK      0x0F
+#define CFG_LBO_unk       0     /* <not defined> */
+#define CFG_LBO_LH0       1     /* T1 Long Haul (default) */
+#define CFG_LBO_LH7_5     2     /* T1 Long Haul */
+#define CFG_LBO_LH15      3     /* T1 Long Haul */
+#define CFG_LBO_LH22_5    4     /* T1 Long Haul */
+#define CFG_LBO_SH110     5     /* T1 Short Haul */
+#define CFG_LBO_SH220     6     /* T1 Short Haul */
+#define CFG_LBO_SH330     7     /* T1 Short Haul */
+#define CFG_LBO_SH440     8     /* T1 Short Haul */
+#define CFG_LBO_SH550     9     /* T1 Short Haul */
+#define CFG_LBO_SH660     10    /* T1 Short Haul */
+#define CFG_LBO_E75       11    /* E1 75 Ohm */
+#define CFG_LBO_E120      12    /* E1 120 Ohm (default) */
+
+
+/*************************************/
+/**  read write channel parameters  **/
+/*************************************/
+
+/* routine/ioctl: wancfg_getset_chan_param() - SBE_IOC_CHAN_GET */
+/* routine/ioctl: wancfg_set_chan_param() - SBE_IOC_CHAN_SET */
+
+/* NOTE: this structure supports hardware which supports individual per/channel control */
+
+    struct sbecom_chan_param
+    {
+        u_int32_t   channum;    /* 0: */
+#ifdef SBE_PMCC4_ENABLE
+       u_int32_t   card;  /* RLD DEBUG - add this in until I learn how to make this entry obsolete */
+       u_int32_t   port;  /* RLD DEBUG - add this in until I learn how to make this entry obsolete */
+       u_int8_t bitmask[32];
+#endif
+        u_int32_t   intr_mask;  /* 4: interrupt mask, specify ored
+                                 * (SS7_)INTR_* to disable */
+        u_int8_t    status;     /* 8: channel transceiver status (TX_ENABLED,
+                                 * RX_ENABLED) */
+        u_int8_t    chan_mode;  /* 9: protocol mode */
+        u_int8_t    idlecode;   /* A: idle code, in (FLAG_7E, FLAG_FF,
+                                 * FLAG_00) */
+        u_int8_t    pad_fill_count;     /* B: pad fill count (1-127), 0 - pad
+                                         * fill disabled */
+        u_int8_t    data_inv;   /* C: channel data inversion selection */
+        u_int8_t    mode_56k;   /* D: 56kbps mode */
+        u_int8_t    reserved[2 + 8];    /* E: */
+    };
+
+/* SS7 interrupt signals <intr_mask> */
+#define SS7_INTR_SFILT      0x00000020
+#define SS7_INTR_SDEC       0x00000040
+#define SS7_INTR_SINC       0x00000080
+#define SS7_INTR_SUERR      0x00000100
+/* Other interrupts that can be masked */
+#define INTR_BUFF           0x00000002
+#define INTR_EOM            0x00000004
+#define INTR_MSG            0x00000008
+#define INTR_IDLE           0x00000010
+
+/* transceiver status flags <status> */
+#define TX_ENABLED          0x01
+#define RX_ENABLED          0x02
+
+/* Protocol modes <mode> */
+#define CFG_CH_PROTO_TRANS         0
+#define CFG_CH_PROTO_SS7           1
+#define CFG_CH_PROTO_HDLC_FCS16    2
+#define CFG_CH_PROTO_HDLC_FCS32    3
+#define CFG_CH_PROTO_ISLP_MODE     4
+
+/* Possible idle code assignments <idlecode> */
+#define CFG_CH_FLAG_7E      0
+#define CFG_CH_FLAG_FF      1
+#define CFG_CH_FLAG_00      2
+
+/* data inversion selection <data_inv> */
+#define CFG_CH_DINV_NONE    0x00
+#define CFG_CH_DINV_RX      0x01
+#define CFG_CH_DINV_TX      0x02
+
+
+/* Posssible resettable chipsets/functions */
+#define RESET_DEV_TEMUX     1
+#define RESET_DEV_TECT3     RESET_DEV_TEMUX
+#define RESET_DEV_PLL       2
+
+
+/*********************************************/
+/**  read reset channel thruput statistics  **/
+/*********************************************/
+
+/* routine/ioctl: wancfg_get_chan_stats() - SBE_IOC_CHAN_GET_STAT */
+/* routine/ioctl: wancfg_del_chan_stats() - SBE_IOC_CHAN_DEL_STAT */
+/* routine/ioctl: wancfg_get_card_chan_stats() - SBE_IOC_CARD_CHAN_STAT */
+
+    struct sbecom_chan_stats
+    {
+        unsigned long rx_packets;       /* total packets received       */
+        unsigned long tx_packets;       /* total packets transmitted    */
+        unsigned long rx_bytes; /* total bytes received         */
+        unsigned long tx_bytes; /* total bytes transmitted      */
+        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  */
+
+        /* 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_fifo_errors;
+        unsigned long tx_pending;
+    };
+
+
+/****************************************/
+/**  read write card level parameters  **/
+/****************************************/
+
+ /* NOTE: this structure supports hardware which supports per/card control */
+
+    struct sbecom_card_param
+    {
+        u_int8_t    framing_type;       /* 0: CBP or M13 */
+        u_int8_t    loopback;   /* 1: one of LOOPBACK_* */
+        u_int8_t    line_build_out;     /* 2: boolean */
+        u_int8_t    receive_eq; /* 3: boolean */
+        u_int8_t    transmit_ones;      /* 4: boolean */
+        u_int8_t    clock;      /* 5: 0 - internal, i>0 - external (recovered
+                                 * from framer i) */
+        u_int8_t    h110enable; /* 6: */
+        u_int8_t    disable_leds;       /* 7: */
+        u_int8_t    reserved1;  /* 8: available - old 256t3 hypersized, but
+                                 * never used */
+        u_int8_t    rear_io;    /* 9: rear I/O off/on */
+        u_int8_t    disable_tx; /* A: disable TX off/on */
+        u_int8_t    mute_los;   /* B: mute LOS off/on */
+        u_int8_t    los_threshold;      /* C: LOS threshold norm/low
+                                         * (default: norm) */
+        u_int8_t    ds1_mode;   /* D: DS1 mode T1/E1 (default: T1) */
+        u_int8_t    ds3_unchan; /* E: DS3 unchannelized mode off/on */
+        u_int8_t    reserved[1 + 16];   /* reserved for expansion - must be
+                                         * ZERO filled */
+    };
+
+/* framing types <framing_type> */
+#define FRAMING_M13                0
+#define FRAMING_CBP                1
+
+/* card level loopback options <loopback> */
+#define CFG_CARD_LOOPBACK_NONE     0x00
+#define CFG_CARD_LOOPBACK_DIAG     0x01
+#define CFG_CARD_LOOPBACK_LINE     0x02
+#define CFG_CARD_LOOPBACK_PAYLOAD  0x03
+
+/* line level loopback options <loopback> */
+#define CFG_LIU_LOOPBACK_NONE      0x00
+#define CFG_LIU_LOOPBACK_ANALOG    0x10
+#define CFG_LIU_LOOPBACK_DIGITAL   0x11
+#define CFG_LIU_LOOPBACK_REMOTE    0x12
+
+/* card level clock options <clock> */
+#define CFG_CLK_INTERNAL           0x00
+#define CFG_CLK_EXTERNAL           0x01
+
+/* legacy 256T3 loopback values */
+#define LOOPBACK_NONE              0
+#define LOOPBACK_LIU_ANALOG        1
+#define LOOPBACK_LIU_DIGITAL       2
+#define LOOPBACK_FRAMER_DS3        3
+#define LOOPBACK_FRAMER_T1         4
+#define LOOPBACK_LIU_REMOTE        5
+
+/* DS1 mode <ds1_mode> */
+#define CFG_DS1_MODE_MASK          0x0f
+#define CFG_DS1_MODE_T1            0x00
+#define CFG_DS1_MODE_E1            0x01
+#define CFG_DS1_MODE_CHANGE        0x80
+
+/* DS3 unchannelized values <ds1_unchan> */
+#define CFG_DS3_UNCHAN_MASK        0x01
+#define CFG_DS3_UNCHAN_OFF         0x00
+#define CFG_DS3_UNCHAN_ON          0x01
+
+
+/************************************/
+/**  read write framer parameters  **/
+/************************************/
+
+/* routine/ioctl: wancfg_get_framer() - SBE_IOC_FRAMER_GET */
+/* routine/ioctl: wancfg_set_framer() - SBE_IOC_FRAMER_SET */
+
+    struct sbecom_framer_param
+    {
+        u_int8_t    framer_num;
+        u_int8_t    frame_type; /* SF, ESF, E1PLAIN, E1CAS, E1CRC, E1CRC+CAS */
+        u_int8_t    loopback_type;      /* DIGITAL, LINE, PAYLOAD */
+        u_int8_t    auto_alarms;/* auto alarms */
+        u_int8_t    reserved[12];       /* reserved for expansion - must be
+                                         * ZERO filled */
+    };
+
+/* frame types <frame_type> */
+#define CFG_FRAME_NONE             0
+#define CFG_FRAME_SF               1    /* T1 B8ZS */
+#define CFG_FRAME_ESF              2    /* T1 B8ZS */
+#define CFG_FRAME_E1PLAIN          3    /* HDB3 w/o CAS,CRC */
+#define CFG_FRAME_E1CAS            4    /* HDB3 */
+#define CFG_FRAME_E1CRC            5    /* HDB3 */
+#define CFG_FRAME_E1CRC_CAS        6    /* HDB3 */
+#define CFG_FRAME_SF_AMI           7    /* T1 AMI */
+#define CFG_FRAME_ESF_AMI          8    /* T1 AMI */
+#define CFG_FRAME_E1PLAIN_AMI      9    /* E1 AMI w/o CAS,CRC */
+#define CFG_FRAME_E1CAS_AMI       10    /* E1 AMI */
+#define CFG_FRAME_E1CRC_AMI       11    /* E1 AMI */
+#define CFG_FRAME_E1CRC_CAS_AMI   12    /* E1 AMI */
+
+#define IS_FRAME_ANY_T1(field) \
+                    (((field) == CFG_FRAME_NONE) || \
+                     ((field) == CFG_FRAME_SF)   || \
+                     ((field) == CFG_FRAME_ESF)  || \
+                     ((field) == CFG_FRAME_SF_AMI) || \
+                     ((field) == CFG_FRAME_ESF_AMI))
+
+#define IS_FRAME_ANY_T1ESF(field) \
+                    (((field) == CFG_FRAME_ESF) || \
+                     ((field) == CFG_FRAME_ESF_AMI))
+
+#define IS_FRAME_ANY_E1(field) \
+                    (((field) == CFG_FRAME_E1PLAIN) || \
+                     ((field) == CFG_FRAME_E1CAS)   || \
+                     ((field) == CFG_FRAME_E1CRC)   || \
+                     ((field) == CFG_FRAME_E1CRC_CAS) || \
+                     ((field) == CFG_FRAME_E1PLAIN_AMI) || \
+                     ((field) == CFG_FRAME_E1CAS_AMI) || \
+                     ((field) == CFG_FRAME_E1CRC_AMI) || \
+                     ((field) == CFG_FRAME_E1CRC_CAS_AMI))
+
+#define IS_FRAME_ANY_AMI(field) \
+                    (((field) == CFG_FRAME_SF_AMI) || \
+                     ((field) == CFG_FRAME_ESF_AMI) || \
+                     ((field) == CFG_FRAME_E1PLAIN_AMI) || \
+                     ((field) == CFG_FRAME_E1CAS_AMI) || \
+                     ((field) == CFG_FRAME_E1CRC_AMI) || \
+                     ((field) == CFG_FRAME_E1CRC_CAS_AMI))
+
+/* frame level loopback options <loopback_type> */
+#define CFG_FRMR_LOOPBACK_NONE     0
+#define CFG_FRMR_LOOPBACK_DIAG     1
+#define CFG_FRMR_LOOPBACK_LINE     2
+#define CFG_FRMR_LOOPBACK_PAYLOAD  3
+
+
+/****************************************/
+/**  read reset card error statistics  **/
+/****************************************/
+
+/* routine/ioctl: wancfg_get_card_stats() - SBE_IOC_CARD_GET_STAT */
+/* routine/ioctl: wancfg_del_card_stats() - SBE_IOC_CARD_DEL_STAT */
+
+    struct temux_card_stats
+    {
+        struct temux_stats
+        {
+            /* TEMUX DS3 PMON counters */
+            u_int32_t   lcv;
+            u_int32_t   err_framing;
+            u_int32_t   febe;
+            u_int32_t   err_cpbit;
+            u_int32_t   err_parity;
+            /* TEMUX DS3 FRMR status */
+            u_int8_t    los;
+            u_int8_t    oof;
+            u_int8_t    red;
+            u_int8_t    yellow;
+            u_int8_t    idle;
+            u_int8_t    ais;
+            u_int8_t    cbit;
+            /* TEMUX DS3 FEAC receiver */
+            u_int8_t    feac;
+            u_int8_t    feac_last;
+        }           t;
+        u_int32_t   tx_pending; /* total */
+    };
+
+/**************************************************************/
+
+    struct wancfg
+    {
+        int         cs, ds;
+        char       *p;
+    };
+    typedef struct wancfg wcfg_t;
+
+    extern wcfg_t *wancfg_init (char *, char *);
+    extern int  wancfg_card_blink (wcfg_t *, int);
+    extern int  wancfg_ctl (wcfg_t *, int, void *, int, void *, int);
+    extern int  wancfg_del_card_stats (wcfg_t *);
+    extern int  wancfg_del_chan_stats (wcfg_t *, int);
+    extern int  wancfg_enable_ports (wcfg_t *, int);
+    extern int  wancfg_free (wcfg_t *);
+    extern int  wancfg_get_brdaddr (wcfg_t *, struct sbe_brd_addr *);
+    extern int  wancfg_get_brdinfo (wcfg_t *, struct sbe_brd_info *);
+    extern int  wancfg_get_card (wcfg_t *, struct sbecom_card_param *);
+    extern int  wancfg_get_card_chan_stats (wcfg_t *, struct sbecom_chan_stats *);
+    extern int  wancfg_get_card_sn (wcfg_t *);
+    extern int  wancfg_get_card_stats (wcfg_t *, struct temux_card_stats *);
+    extern int  wancfg_get_chan (wcfg_t *, int, struct sbecom_chan_param *);
+    extern int  wancfg_get_chan_stats (wcfg_t *, int, struct sbecom_chan_stats *);
+    extern int  wancfg_get_drvinfo (wcfg_t *, int, struct sbe_drv_info *);
+    extern int  wancfg_get_framer (wcfg_t *, int, struct sbecom_framer_param *);
+    extern int  wancfg_get_iid (wcfg_t *, int, struct sbe_iid_info *);
+    extern int  wancfg_get_sn (wcfg_t *, unsigned int *);
+    extern int  wancfg_read (wcfg_t *, int, struct sbecom_wrt_vec *);
+    extern int  wancfg_reset_device (wcfg_t *, int);
+    extern int  wancfg_set_card (wcfg_t *, struct sbecom_card_param *);
+    extern int  wancfg_set_chan (wcfg_t *, int, struct sbecom_chan_param *);
+    extern int  wancfg_set_framer (wcfg_t *, int, struct sbecom_framer_param *);
+    extern int  wancfg_set_loglevel (wcfg_t *, uint);
+    extern int  wancfg_write (wcfg_t *, int, struct sbecom_wrt_vec *);
+
+#ifdef NOT_YET_COMMON
+    extern int  wancfg_get_tsioc (wcfg_t *, struct wanc1t3_ts_hdr *, struct wanc1t3_ts_param *);
+    extern int  wancfg_set_tsioc (wcfg_t *, struct wanc1t3_ts_param *);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif                          /*** _INC_LIBSBEW_H_ ***/
diff --git a/drivers/staging/cxt1e1/linux.c b/drivers/staging/cxt1e1/linux.c
new file mode 100644 (file)
index 0000000..23e184d
--- /dev/null
@@ -0,0 +1,1354 @@
+/* Copyright (C) 2007-2008  One Stop Systems
+ * Copyright (C) 2003-2006  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/hdlc.h>
+#include <linux/if_arp.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/rtnetlink.h>
+#include <linux/skbuff.h>
+#include "pmcc4_sysdep.h"
+#include "sbecom_inline_linux.h"
+#include "libsbew.h"
+#include "pmcc4.h"
+#include "pmcc4_ioctls.h"
+#include "pmcc4_private.h"
+#include "sbeproc.h"
+
+/*****************************************************************************************
+ * Error out early if we have compiler trouble.
+ *
+ *   (This section is included from the kernel's init/main.c as a friendly
+ *   spiderman recommendation...)
+ *
+ * Versions of gcc older than that listed below may actually compile and link
+ * okay, but the end product can have subtle run time bugs.  To avoid associated
+ * bogus bug reports, we flatly refuse to compile with a gcc that is known to be
+ * too old from the very beginning.
+ */
+#if (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 2)
+#error Sorry, your GCC is too old. It builds incorrect kernels.
+#endif
+
+#if __GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ == 0
+#warning gcc-4.1.0 is known to miscompile the kernel.  A different compiler version is recommended.
+#endif
+
+/*****************************************************************************************/
+
+#ifdef SBE_INCLUDE_SYMBOLS
+#define STATIC
+#else
+#define STATIC  static
+#endif
+
+#define CHANNAME "hdlc"
+
+/*******************************************************************/
+/* forward references */
+status_t    c4_chan_work_init (mpi_t *, mch_t *);
+void        musycc_wq_chan_restart (void *);
+status_t __init c4_init (ci_t *, u_char *, u_char *);
+status_t __init c4_init2 (ci_t *);
+ci_t       *__init c4_new (void *);
+int __init  c4hw_attach_all (void);
+void __init hdw_sn_get (hdw_info_t *, int);
+
+#ifdef CONFIG_SBE_PMCC4_NCOMM
+irqreturn_t c4_ebus_intr_th_handler (void *);
+
+#endif
+int         c4_frame_rw (ci_t *, struct sbecom_port_param *);
+status_t    c4_get_port (ci_t *, int);
+int         c4_loop_port (ci_t *, int, u_int8_t);
+int         c4_musycc_rw (ci_t *, struct c4_musycc_param *);
+int         c4_new_chan (ci_t *, int, int, void *);
+status_t    c4_set_port (ci_t *, int);
+int         c4_pld_rw (ci_t *, struct sbecom_port_param *);
+void        cleanup_devs (void);
+void        cleanup_ioremap (void);
+status_t    musycc_chan_down (ci_t *, int);
+irqreturn_t musycc_intr_th_handler (void *);
+int         musycc_start_xmit (ci_t *, int, void *);
+
+extern char pmcc4_OSSI_release[];
+extern ci_t *CI;
+extern struct s_hdw_info hdw_info[];
+
+#if defined(CONFIG_SBE_HDLC_V7) || defined(CONFIG_SBE_WAN256T3_HDLC_V7) || \
+    defined(CONFIG_SBE_HDLC_V7_MODULE) || defined(CONFIG_SBE_WAN256T3_HDLC_V7_MODULE)
+#define _v7_hdlc_  1
+#else
+#define _v7_hdlc_  0
+#endif
+
+#if _v7_hdlc_
+#define V7(x) (x ## _v7)
+extern int  hdlc_netif_rx_v7 (hdlc_device *, struct sk_buff *);
+extern int  register_hdlc_device_v7 (hdlc_device *);
+extern int  unregister_hdlc_device_v7 (hdlc_device *);
+
+#else
+#define V7(x) x
+#endif
+
+int         error_flag;         /* module load error reporting */
+int         log_level = LOG_ERROR;
+int         log_level_default = LOG_ERROR;
+module_param(log_level, int, 0444);
+
+int         max_mru = MUSYCC_MRU;
+int         max_mru_default = MUSYCC_MRU;
+module_param(max_mru, int, 0444);
+
+int         max_mtu = MUSYCC_MTU;
+int         max_mtu_default = MUSYCC_MTU;
+module_param(max_mtu, int, 0444);
+
+int         max_txdesc_used = MUSYCC_TXDESC_MIN;
+int         max_txdesc_default = MUSYCC_TXDESC_MIN;
+module_param(max_txdesc_used, int, 0444);
+
+int         max_rxdesc_used = MUSYCC_RXDESC_MIN;
+int         max_rxdesc_default = MUSYCC_RXDESC_MIN;
+module_param(max_rxdesc_used, int, 0444);
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+void       *
+getuserbychan (int channum)
+{
+    mch_t      *ch;
+
+    ch = c4_find_chan (channum);
+    return ch ? ch->user : 0;
+}
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#define DEV_TO_PRIV(dev) ( * (struct c4_priv **) ((hdlc_device*)(dev)+1))
+#else
+
+char       *
+get_hdlc_name (hdlc_device * hdlc)
+{
+    struct c4_priv *priv = hdlc->priv;
+    struct net_device *dev = getuserbychan (priv->channum);
+
+    return dev->name;
+}
+#endif
+
+
+static      status_t
+mkret (int bsd)
+{
+    if (bsd > 0)
+        return -bsd;
+    else
+        return bsd;
+}
+
+/***************************************************************************/
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
+#include <linux/workqueue.h>
+
+/***
+ * One workqueue (wq) per port (since musycc allows simultaneous group
+ * commands), with individual data for each channel:
+ *
+ *   mpi_t -> struct workqueue_struct *wq_port;  (dynamically allocated using
+ *                                               create_workqueue())
+ *
+ * With work structure (work) statically allocated for each channel:
+ *
+ *   mch_t -> struct work_struct ch_work;  (statically allocated using ???)
+ *
+ ***/
+
+
+/*
+ * Called by the start transmit routine when a channel TX_ENABLE is to be
+ * issued.  This queues the transmission start request among other channels
+ * within a port's group.
+ */
+void
+c4_wk_chan_restart (mch_t * ch)
+{
+    mpi_t      *pi = ch->up;
+
+#ifdef RLD_RESTART_DEBUG
+    printk (">> c4_wk_chan_restart: queueing Port %d Chan %d, mch_t @ %p\n", pi->portnum, ch->channum, ch);
+#endif
+
+    /* create new entry w/in workqueue for this channel and let'er rip */
+
+    /** queue_work (struct workqueue_struct *queue,
+     **             struct work_struct *work);
+     **/
+    queue_work (pi->wq_port, &ch->ch_work);
+}
+
+status_t
+c4_wk_chan_init (mpi_t * pi, mch_t * ch)
+{
+    /*
+     * this will be used to restart a stopped channel
+     */
+
+    /** INIT_WORK (struct work_struct *work,
+     **            void (*function)(void *),
+     **            void *data);
+     **/
+    INIT_WORK(&ch->ch_work, (void *)musycc_wq_chan_restart);
+    return 0;                       /* success */
+}
+
+status_t
+c4_wq_port_init (mpi_t * pi)
+{
+
+    char        name[16], *np;  /* NOTE: name of the queue limited by system
+                                 * to 10 characters */
+
+    if (pi->wq_port)
+        return 0;                   /* already initialized */
+
+    np = name;
+    memset (name, 0, 16);
+    sprintf (np, "%s%d", pi->up->devname, pi->portnum); /* IE pmcc4-01) */
+
+#ifdef RLD_RESTART_DEBUG
+    printk (">> c4_wq_port_init: creating workqueue <%s> for Port %d.\n", name, pi->portnum); /* RLD DEBUG */
+#endif
+    if (!(pi->wq_port = create_singlethread_workqueue (name)))
+        return ENOMEM;
+    return 0;                       /* success */
+}
+
+void
+c4_wq_port_cleanup (mpi_t * pi)
+{
+    /*
+     * PORT POINT: cannot call this if WQ is statically allocated w/in
+     * structure since it calls kfree(wq);
+     */
+    if (pi->wq_port)
+    {
+        destroy_workqueue (pi->wq_port);        /* this also calls
+                                                 * flush_workqueue() */
+        pi->wq_port = 0;
+    }
+}
+#endif
+
+/***************************************************************************/
+
+irqreturn_t
+c4_linux_interrupt (int irq, void *dev_instance)
+{
+    struct net_device *ndev = dev_instance;
+
+    return musycc_intr_th_handler(netdev_priv(ndev));
+}
+
+
+#ifdef CONFIG_SBE_PMCC4_NCOMM
+irqreturn_t
+c4_ebus_interrupt (int irq, void *dev_instance)
+{
+    struct net_device *ndev = dev_instance;
+
+    return c4_ebus_intr_th_handler(netdev_priv(ndev));
+}
+#endif
+
+
+static int
+void_open (struct net_device * ndev)
+{
+    printk ("%s: trying to open master device !\n", ndev->name);
+    return -1;
+}
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#if !defined(GENERIC_HDLC_VERSION) || (GENERIC_HDLC_VERSION < 4)
+
+/** Linux 2.4.18-19 **/
+STATIC int
+chan_open (hdlc_device * hdlc)
+{
+    status_t    ret;
+
+    if ((ret = c4_chan_up (DEV_TO_PRIV (hdlc)->ci, DEV_TO_PRIV (hdlc)->channum)))
+        return -ret;
+    MOD_INC_USE_COUNT;
+    netif_start_queue (hdlc_to_dev (hdlc));
+    return 0;                       /* no error = success */
+}
+
+#else
+
+/** Linux 2.4.20 and higher **/
+STATIC int
+chan_open (struct net_device * ndev)
+{
+    hdlc_device *hdlc = dev_to_hdlc (ndev);
+    status_t    ret;
+
+    hdlc->proto = IF_PROTO_HDLC;
+    if ((ret = hdlc_open (hdlc)))
+    {
+        printk ("%s: hdlc_open failure, err %d.\n", THIS_MODULE->name, ret);
+        return ret;
+    }
+    if ((ret = c4_chan_up (DEV_TO_PRIV (hdlc)->ci, DEV_TO_PRIV (hdlc)->channum)))
+        return -ret;
+    MOD_INC_USE_COUNT;
+    netif_start_queue (hdlc_to_dev (hdlc));
+    return 0;                       /* no error = success */
+}
+#endif
+
+#else
+
+/** Linux 2.6 **/
+STATIC int
+chan_open (struct net_device * ndev)
+{
+    hdlc_device *hdlc = dev_to_hdlc (ndev);
+    const struct c4_priv *priv = hdlc->priv;
+    int         ret;
+
+    if ((ret = hdlc_open (ndev)))
+    {
+        printk ("%s: hdlc_open failure, err %d.\n", THIS_MODULE->name, ret);
+        return ret;
+    }
+    if ((ret = c4_chan_up (priv->ci, priv->channum)))
+        return -ret;
+    try_module_get (THIS_MODULE);
+    netif_start_queue (ndev);
+    return 0;                       /* no error = success */
+}
+#endif
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#if !defined(GENERIC_HDLC_VERSION) || (GENERIC_HDLC_VERSION < 4)
+
+/** Linux 2.4.18-19 **/
+STATIC void
+chan_close (hdlc_device * hdlc)
+{
+    netif_stop_queue (hdlc_to_dev (hdlc));
+    musycc_chan_down ((ci_t *) 0, DEV_TO_PRIV (hdlc)->channum);
+    MOD_DEC_USE_COUNT;
+}
+#else
+
+/** Linux 2.4.20 and higher **/
+STATIC int
+chan_close (struct net_device * ndev)
+{
+    hdlc_device *hdlc = dev_to_hdlc (ndev);
+
+    netif_stop_queue (hdlc_to_dev (hdlc));
+    musycc_chan_down ((ci_t *) 0, DEV_TO_PRIV (hdlc)->channum);
+    hdlc_close (hdlc);
+    MOD_DEC_USE_COUNT;
+    return 0;
+}
+#endif
+
+#else
+
+/** Linux 2.6 **/
+STATIC int
+chan_close (struct net_device * ndev)
+{
+    hdlc_device *hdlc = dev_to_hdlc (ndev);
+    const struct c4_priv *priv = hdlc->priv;
+
+    netif_stop_queue (ndev);
+    musycc_chan_down ((ci_t *) 0, priv->channum);
+    hdlc_close (ndev);
+    module_put (THIS_MODULE);
+    return 0;
+}
+#endif
+
+
+#if !defined(GENERIC_HDLC_VERSION) || (GENERIC_HDLC_VERSION < 4)
+
+/** Linux 2.4.18-19 **/
+STATIC int
+chan_ioctl (hdlc_device * hdlc, struct ifreq * ifr, int cmd)
+{
+    if (cmd == HDLCSCLOCK)
+    {
+        ifr->ifr_ifru.ifru_ivalue = LINE_DEFAULT;
+        return 0;
+    }
+    return -EINVAL;
+}
+#endif
+
+
+#if !defined(GENERIC_HDLC_VERSION) || (GENERIC_HDLC_VERSION < 4)
+STATIC int
+chan_dev_ioctl (struct net_device * hdlc, struct ifreq * ifr, int cmd)
+{
+    if (cmd == HDLCSCLOCK)
+    {
+        ifr->ifr_ifru.ifru_ivalue = LINE_DEFAULT;
+        return 0;
+    }
+    return -EINVAL;
+}
+#else
+STATIC int
+chan_dev_ioctl (struct net_device * dev, struct ifreq * ifr, int cmd)
+{
+    return hdlc_ioctl (dev, ifr, cmd);
+}
+
+
+STATIC int
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+chan_attach_noop (hdlc_device * hdlc, unsigned short foo_1, unsigned short foo_2)
+#else
+chan_attach_noop (struct net_device * ndev, unsigned short foo_1, unsigned short foo_2)
+#endif
+{
+    return 0;                   /* our driver has nothing to do here, show's
+                                 * over, go home */
+}
+#endif
+
+
+STATIC struct net_device_stats *
+chan_get_stats (struct net_device * ndev)
+{
+    mch_t      *ch;
+    struct net_device_stats *nstats;
+    struct sbecom_chan_stats *stats;
+    int         channum;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+    channum = DEV_TO_PRIV (ndev)->channum;
+#else
+    {
+        struct c4_priv *priv;
+
+        priv = (struct c4_priv *) dev_to_hdlc (ndev)->priv;
+        channum = priv->channum;
+    }
+#endif
+
+    ch = c4_find_chan (channum);
+    if (ch == NULL)
+        return NULL;
+
+    nstats = &ndev->stats;
+    stats = &ch->s;
+
+    memset (nstats, 0, sizeof (struct net_device_stats));
+    nstats->rx_packets = stats->rx_packets;
+    nstats->tx_packets = stats->tx_packets;
+    nstats->rx_bytes = stats->rx_bytes;
+    nstats->tx_bytes = stats->tx_bytes;
+    nstats->rx_errors = stats->rx_length_errors +
+        stats->rx_over_errors +
+        stats->rx_crc_errors +
+        stats->rx_frame_errors +
+        stats->rx_fifo_errors +
+        stats->rx_missed_errors;
+    nstats->tx_errors = stats->tx_dropped +
+        stats->tx_aborted_errors +
+        stats->tx_fifo_errors;
+    nstats->rx_dropped = stats->rx_dropped;
+    nstats->tx_dropped = stats->tx_dropped;
+
+    nstats->rx_length_errors = stats->rx_length_errors;
+    nstats->rx_over_errors = stats->rx_over_errors;
+    nstats->rx_crc_errors = stats->rx_crc_errors;
+    nstats->rx_frame_errors = stats->rx_frame_errors;
+    nstats->rx_fifo_errors = stats->rx_fifo_errors;
+    nstats->rx_missed_errors = stats->rx_missed_errors;
+
+    nstats->tx_aborted_errors = stats->tx_aborted_errors;
+    nstats->tx_fifo_errors = stats->tx_fifo_errors;
+
+    return nstats;
+}
+
+
+static ci_t *
+get_ci_by_dev (struct net_device * ndev)
+{
+    return (ci_t *)(netdev_priv(ndev));
+}
+
+
+#if !defined(GENERIC_HDLC_VERSION) || (GENERIC_HDLC_VERSION < 4)
+STATIC int
+c4_linux_xmit (hdlc_device * hdlc, struct sk_buff * skb)
+{
+    int         rval;
+
+    rval = musycc_start_xmit (DEV_TO_PRIV (hdlc)->ci, DEV_TO_PRIV (hdlc)->channum, skb);
+    return -rval;
+}
+#else                           /* new */
+STATIC int
+c4_linux_xmit (struct sk_buff * skb, struct net_device * ndev)
+{
+    const struct c4_priv *priv;
+    int         rval;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+    priv = DEV_TO_PRIV (ndev);
+#else
+    hdlc_device *hdlc = dev_to_hdlc (ndev);
+
+    priv = hdlc->priv;
+#endif
+
+    rval = musycc_start_xmit (priv->ci, priv->channum, skb);
+    return -rval;
+}
+#endif                          /* GENERIC_HDLC_VERSION */
+
+static const struct net_device_ops chan_ops = {
+       .ndo_open       = chan_open,
+       .ndo_stop       = chan_close,
+       .ndo_start_xmit = c4_linux_xmit,
+       .ndo_do_ioctl   = chan_dev_ioctl,
+       .ndo_get_stats  = chan_get_stats,
+};
+
+STATIC struct net_device *
+create_chan (struct net_device * ndev, ci_t * ci,
+             struct sbecom_chan_param * cp)
+{
+    hdlc_device *hdlc;
+    struct net_device *dev;
+    hdw_info_t *hi;
+    int         ret;
+
+    if (c4_find_chan (cp->channum))
+        return 0;                   /* channel already exists */
+
+    {
+        struct c4_priv *priv;
+
+        /* allocate then fill in private data structure */
+        priv = OS_kmalloc (sizeof (struct c4_priv));
+        if (!priv)
+        {
+            printk (KERN_WARNING "%s: no memory for net_device !\n", ci->devname);
+            return 0;
+        }
+        dev = alloc_hdlcdev (priv);
+        if (!dev)
+        {
+            printk (KERN_WARNING "%s: no memory for hdlc_device !\n", ci->devname);
+            OS_kfree (priv);
+            return 0;
+        }
+        priv->ci = ci;
+        priv->channum = cp->channum;
+    }
+
+    hdlc = dev_to_hdlc (dev);
+
+    dev->base_addr = 0;             /* not I/O mapped */
+    dev->irq = ndev->irq;
+    dev->type = ARPHRD_RAWHDLC;
+    *dev->name = 0;                 /* default ifconfig name = "hdlc" */
+
+    hi = (hdw_info_t *) ci->hdw_info;
+    if (hi->mfg_info_sts == EEPROM_OK)
+    {
+        switch (hi->promfmt)
+        {
+        case PROM_FORMAT_TYPE1:
+            memcpy (dev->dev_addr, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
+            break;
+        case PROM_FORMAT_TYPE2:
+            memcpy (dev->dev_addr, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
+            break;
+        default:
+            memset (dev->dev_addr, 0, 6);
+            break;
+        }
+    } else
+    {
+        memset (dev->dev_addr, 0, 6);
+    }
+
+    hdlc->xmit = c4_linux_xmit;
+
+    dev->netdev_ops = &chan_ops;
+    /*
+     * The native hdlc stack calls this 'attach' routine during
+     * hdlc_raw_ioctl(), passing parameters for line encoding and parity.
+     * Since hdlc_raw_ioctl() stack does not interrogate whether an 'attach'
+     * routine is actually registered or not, we supply a dummy routine which
+     * does nothing (since encoding and parity are setup for our driver via a
+     * special configuration application).
+     */
+
+    hdlc->attach = chan_attach_noop;
+
+    rtnl_unlock ();                 /* needed due to Ioctl calling sequence */
+    ret = register_hdlc_device (dev);
+    /* NOTE: <stats> setting must occur AFTER registration in order to "take" */
+    dev->tx_queue_len = MAX_DEFAULT_IFQLEN;
+
+    rtnl_lock ();                   /* needed due to Ioctl calling sequence */
+    if (ret)
+    {
+        if (log_level >= LOG_WARN)
+            printk ("%s: create_chan[%d] registration error = %d.\n",
+                    ci->devname, cp->channum, ret);
+        free_netdev (dev);          /* cleanup */
+        return 0;                   /* failed to register */
+    }
+    return dev;
+}
+
+
+/* the idea here is to get port information and pass it back (using pointer) */
+STATIC      status_t
+do_get_port (struct net_device * ndev, void *data)
+{
+    int         ret;
+    ci_t       *ci;             /* ci stands for card information */
+    struct sbecom_port_param pp;/* copy data to kernel land */
+
+    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
+        return -EFAULT;
+    if (pp.portnum >= MUSYCC_NPORTS)
+        return -EFAULT;
+    ci = get_ci_by_dev (ndev);
+    if (!ci)
+        return -EINVAL;             /* get card info */
+
+    ret = mkret (c4_get_port (ci, pp.portnum));
+    if (ret)
+        return ret;
+    if (copy_to_user (data, &ci->port[pp.portnum].p,
+                      sizeof (struct sbecom_port_param)))
+        return -EFAULT;
+    return 0;
+}
+
+/* this function copys the user data and then calls the real action function */
+STATIC      status_t
+do_set_port (struct net_device * ndev, void *data)
+{
+    ci_t       *ci;             /* ci stands for card information */
+    struct sbecom_port_param pp;/* copy data to kernel land */
+
+    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
+        return -EFAULT;
+    if (pp.portnum >= MUSYCC_NPORTS)
+        return -EFAULT;
+    ci = get_ci_by_dev (ndev);
+    if (!ci)
+        return -EINVAL;             /* get card info */
+
+    if (pp.portnum >= ci->max_port) /* sanity check */
+        return ENXIO;
+
+    memcpy (&ci->port[pp.portnum].p, &pp, sizeof (struct sbecom_port_param));
+    return mkret (c4_set_port (ci, pp.portnum));
+}
+
+/* work the port loopback mode as per directed */
+STATIC      status_t
+do_port_loop (struct net_device * ndev, void *data)
+{
+    struct sbecom_port_param pp;
+    ci_t       *ci;
+
+    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
+        return -EFAULT;
+    ci = get_ci_by_dev (ndev);
+    if (!ci)
+        return -EINVAL;
+    return mkret (c4_loop_port (ci, pp.portnum, pp.port_mode));
+}
+
+/* set the specified register with the given value / or just read it */
+STATIC      status_t
+do_framer_rw (struct net_device * ndev, void *data)
+{
+    struct sbecom_port_param pp;
+    ci_t       *ci;
+    int         ret;
+
+    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
+        return -EFAULT;
+    ci = get_ci_by_dev (ndev);
+    if (!ci)
+        return -EINVAL;
+    ret = mkret (c4_frame_rw (ci, &pp));
+    if (ret)
+        return ret;
+    if (copy_to_user (data, &pp, sizeof (struct sbecom_port_param)))
+        return -EFAULT;
+    return 0;
+}
+
+/* set the specified register with the given value / or just read it */
+STATIC      status_t
+do_pld_rw (struct net_device * ndev, void *data)
+{
+    struct sbecom_port_param pp;
+    ci_t       *ci;
+    int         ret;
+
+    if (copy_from_user (&pp, data, sizeof (struct sbecom_port_param)))
+        return -EFAULT;
+    ci = get_ci_by_dev (ndev);
+    if (!ci)
+        return -EINVAL;
+    ret = mkret (c4_pld_rw (ci, &pp));
+    if (ret)
+        return ret;
+    if (copy_to_user (data, &pp, sizeof (struct sbecom_port_param)))
+        return -EFAULT;
+    return 0;
+}
+
+/* set the specified register with the given value / or just read it */
+STATIC      status_t
+do_musycc_rw (struct net_device * ndev, void *data)
+{
+    struct c4_musycc_param mp;
+    ci_t       *ci;
+    int         ret;
+
+    if (copy_from_user (&mp, data, sizeof (struct c4_musycc_param)))
+        return -EFAULT;
+    ci = get_ci_by_dev (ndev);
+    if (!ci)
+        return -EINVAL;
+    ret = mkret (c4_musycc_rw (ci, &mp));
+    if (ret)
+        return ret;
+    if (copy_to_user (data, &mp, sizeof (struct c4_musycc_param)))
+        return -EFAULT;
+    return 0;
+}
+
+STATIC      status_t
+do_get_chan (struct net_device * ndev, void *data)
+{
+    struct sbecom_chan_param cp;
+    int         ret;
+
+    if (copy_from_user (&cp, data,
+                        sizeof (struct sbecom_chan_param)))
+        return -EFAULT;
+
+    if ((ret = mkret (c4_get_chan (cp.channum, &cp))))
+        return ret;
+
+    if (copy_to_user (data, &cp, sizeof (struct sbecom_chan_param)))
+        return -EFAULT;
+    return 0;
+}
+
+STATIC      status_t
+do_set_chan (struct net_device * ndev, void *data)
+{
+    struct sbecom_chan_param cp;
+    int         ret;
+    ci_t       *ci;
+
+    if (copy_from_user (&cp, data, sizeof (struct sbecom_chan_param)))
+        return -EFAULT;
+    ci = get_ci_by_dev (ndev);
+    if (!ci)
+        return -EINVAL;
+    switch (ret = mkret (c4_set_chan (cp.channum, &cp)))
+    {
+    case 0:
+        return 0;
+    default:
+        return ret;
+    }
+}
+
+STATIC      status_t
+do_create_chan (struct net_device * ndev, void *data)
+{
+    ci_t       *ci;
+    struct net_device *dev;
+    struct sbecom_chan_param cp;
+    int         ret;
+
+    if (copy_from_user (&cp, data, sizeof (struct sbecom_chan_param)))
+        return -EFAULT;
+    ci = get_ci_by_dev (ndev);
+    if (!ci)
+        return -EINVAL;
+    dev = create_chan (ndev, ci, &cp);
+    if (!dev)
+        return -EBUSY;
+    ret = mkret (c4_new_chan (ci, cp.port, cp.channum, dev));
+    if (ret)
+    {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+        rtnl_unlock ();             /* needed due to Ioctl calling sequence */
+        V7 (unregister_hdlc_device) (dev_to_hdlc (dev));
+        rtnl_lock ();               /* needed due to Ioctl calling sequence */
+        OS_kfree (DEV_TO_PRIV (dev));
+        OS_kfree (dev);
+#else
+        rtnl_unlock ();             /* needed due to Ioctl calling sequence */
+        unregister_hdlc_device (dev);
+        rtnl_lock ();               /* needed due to Ioctl calling sequence */
+        free_netdev (dev);
+#endif
+    }
+    return ret;
+}
+
+STATIC      status_t
+do_get_chan_stats (struct net_device * ndev, void *data)
+{
+    struct c4_chan_stats_wrap ccs;
+    int         ret;
+
+    if (copy_from_user (&ccs, data,
+                        sizeof (struct c4_chan_stats_wrap)))
+        return -EFAULT;
+    switch (ret = mkret (c4_get_chan_stats (ccs.channum, &ccs.stats)))
+    {
+    case 0:
+        break;
+    default:
+        return ret;
+    }
+    if (copy_to_user (data, &ccs,
+                      sizeof (struct c4_chan_stats_wrap)))
+        return -EFAULT;
+    return 0;
+}
+STATIC      status_t
+do_set_loglevel (struct net_device * ndev, void *data)
+{
+    unsigned int log_level;
+
+    if (copy_from_user (&log_level, data, sizeof (int)))
+        return -EFAULT;
+    sbecom_set_loglevel (log_level);
+    return 0;
+}
+
+STATIC      status_t
+do_deluser (struct net_device * ndev, int lockit)
+{
+    if (ndev->flags & IFF_UP)
+        return -EBUSY;
+
+    {
+        ci_t       *ci;
+        mch_t      *ch;
+        const struct c4_priv *priv;
+        int         channum;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+        priv = DEV_TO_PRIV (ndev);
+#else
+        priv = (struct c4_priv *) dev_to_hdlc (ndev)->priv;
+#endif
+        ci = priv->ci;
+        channum = priv->channum;
+
+        ch = c4_find_chan (channum);
+        if (ch == NULL)
+            return -ENOENT;
+        ch->user = 0;               /* will be freed, below */
+    }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+    if (lockit)
+        rtnl_unlock ();             /* needed if Ioctl calling sequence */
+    V7 (unregister_hdlc_device) (dev_to_hdlc (ndev));
+    if (lockit)
+        rtnl_lock ();               /* needed if Ioctl calling sequence */
+    OS_kfree (DEV_TO_PRIV (ndev));
+    OS_kfree (ndev);
+#else
+    if (lockit)
+        rtnl_unlock ();             /* needed if Ioctl calling sequence */
+    unregister_hdlc_device (ndev);
+    if (lockit)
+        rtnl_lock ();               /* needed if Ioctl calling sequence */
+    free_netdev (ndev);
+#endif
+    return 0;
+}
+
+int
+do_del_chan (struct net_device * musycc_dev, void *data)
+{
+    struct sbecom_chan_param cp;
+    char        buf[sizeof (CHANNAME) + 3];
+    struct net_device *dev;
+    int         ret;
+
+    if (copy_from_user (&cp, data,
+                        sizeof (struct sbecom_chan_param)))
+        return -EFAULT;
+    sprintf (buf, CHANNAME "%d", cp.channum);
+    if (!(dev = dev_get_by_name (&init_net, buf)))
+        return -ENOENT;
+    dev_put (dev);
+    ret = do_deluser (dev, 1);
+    if (ret)
+        return ret;
+    return c4_del_chan (cp.channum);
+}
+int         c4_reset_board (void *);
+
+int
+do_reset (struct net_device * musycc_dev, void *data)
+{
+    const struct c4_priv *priv;
+    int         i;
+
+    for (i = 0; i < 128; i++)
+    {
+        struct net_device *ndev;
+        char        buf[sizeof (CHANNAME) + 3];
+
+        sprintf (buf, CHANNAME "%d", i);
+        if (!(ndev = dev_get_by_name(&init_net, buf)))
+            continue;
+        priv = dev_to_hdlc (ndev)->priv;
+
+        if ((unsigned long) (priv->ci) ==
+            (unsigned long) (netdev_priv(musycc_dev)))
+        {
+            ndev->flags &= ~IFF_UP;
+            dev_put (ndev);
+            netif_stop_queue (ndev);
+            do_deluser (ndev, 1);
+        } else
+            dev_put (ndev);
+    }
+    return 0;
+}
+
+int
+do_reset_chan_stats (struct net_device * musycc_dev, void *data)
+{
+    struct sbecom_chan_param cp;
+
+    if (copy_from_user (&cp, data,
+                        sizeof (struct sbecom_chan_param)))
+        return -EFAULT;
+    return mkret (c4_del_chan_stats (cp.channum));
+}
+
+STATIC      status_t
+c4_ioctl (struct net_device * ndev, struct ifreq * ifr, int cmd)
+{
+    ci_t       *ci;
+    void       *data;
+    int         iocmd, iolen;
+    status_t    ret;
+    static struct data
+    {
+        union
+        {
+            u_int8_t c;
+            u_int32_t i;
+            struct sbe_brd_info bip;
+            struct sbe_drv_info dip;
+            struct sbe_iid_info iip;
+            struct sbe_brd_addr bap;
+            struct sbecom_chan_stats stats;
+            struct sbecom_chan_param param;
+            struct temux_card_stats cards;
+            struct sbecom_card_param cardp;
+            struct sbecom_framer_param frp;
+        }           u;
+    }           arg;
+
+
+    if (!capable (CAP_SYS_ADMIN))
+        return -EPERM;
+    if (cmd != SIOCDEVPRIVATE + 15)
+        return -EINVAL;
+    if (!(ci = get_ci_by_dev (ndev)))
+        return -EINVAL;
+    if (ci->state != C_RUNNING)
+        return -ENODEV;
+    if (copy_from_user (&iocmd, ifr->ifr_data, sizeof (iocmd)))
+        return -EFAULT;
+#if 0
+    if (copy_from_user (&len, ifr->ifr_data + sizeof (iocmd), sizeof (len)))
+        return -EFAULT;
+#endif
+
+#if 0
+    printk ("c4_ioctl: iocmd %x, dir %x type %x nr %x iolen %d.\n", iocmd,
+            _IOC_DIR (iocmd), _IOC_TYPE (iocmd), _IOC_NR (iocmd),
+            _IOC_SIZE (iocmd));
+#endif
+    iolen = _IOC_SIZE (iocmd);
+    data = ifr->ifr_data + sizeof (iocmd);
+    if (copy_from_user (&arg, data, iolen))
+        return -EFAULT;
+
+    ret = 0;
+    switch (iocmd)
+    {
+    case SBE_IOC_PORT_GET:
+        //printk (">> SBE_IOC_PORT_GET Ioctl...\n");
+        ret = do_get_port (ndev, data);
+        break;
+    case SBE_IOC_PORT_SET:
+        //printk (">> SBE_IOC_PORT_SET Ioctl...\n");
+        ret = do_set_port (ndev, data);
+        break;
+    case SBE_IOC_CHAN_GET:
+        //printk (">> SBE_IOC_CHAN_GET Ioctl...\n");
+        ret = do_get_chan (ndev, data);
+        break;
+    case SBE_IOC_CHAN_SET:
+        //printk (">> SBE_IOC_CHAN_SET Ioctl...\n");
+        ret = do_set_chan (ndev, data);
+        break;
+    case C4_DEL_CHAN:
+        //printk (">> C4_DEL_CHAN Ioctl...\n");
+        ret = do_del_chan (ndev, data);
+        break;
+    case SBE_IOC_CHAN_NEW:
+        ret = do_create_chan (ndev, data);
+        break;
+    case SBE_IOC_CHAN_GET_STAT:
+        ret = do_get_chan_stats (ndev, data);
+        break;
+    case SBE_IOC_LOGLEVEL:
+        ret = do_set_loglevel (ndev, data);
+        break;
+    case SBE_IOC_RESET_DEV:
+        ret = do_reset (ndev, data);
+        break;
+    case SBE_IOC_CHAN_DEL_STAT:
+        ret = do_reset_chan_stats (ndev, data);
+        break;
+    case C4_LOOP_PORT:
+        ret = do_port_loop (ndev, data);
+        break;
+    case C4_RW_FRMR:
+        ret = do_framer_rw (ndev, data);
+        break;
+    case C4_RW_MSYC:
+        ret = do_musycc_rw (ndev, data);
+        break;
+    case C4_RW_PLD:
+        ret = do_pld_rw (ndev, data);
+        break;
+    case SBE_IOC_IID_GET:
+        ret = (iolen == sizeof (struct sbe_iid_info)) ? c4_get_iidinfo (ci, &arg.u.iip) : -EFAULT;
+        if (ret == 0)               /* no error, copy data */
+            if (copy_to_user (data, &arg, iolen))
+                return -EFAULT;
+        break;
+    default:
+        //printk (">> c4_ioctl: EINVAL - unknown iocmd <%x>\n", iocmd);
+        ret = -EINVAL;
+        break;
+    }
+    return mkret (ret);
+}
+
+static const struct net_device_ops c4_ops = {
+       .ndo_open       = void_open,
+       .ndo_start_xmit = c4_linux_xmit,
+       .ndo_do_ioctl   = c4_ioctl,
+};
+
+static void c4_setup(struct net_device *dev)
+{
+       dev->type = ARPHRD_VOID;
+       dev->netdev_ops = &c4_ops;
+}
+
+struct net_device *__init
+c4_add_dev (hdw_info_t * hi, int brdno, unsigned long f0, unsigned long f1,
+            int irq0, int irq1)
+{
+    struct net_device *ndev;
+    ci_t       *ci;
+
+    ndev = alloc_netdev(sizeof(ci_t), SBE_IFACETMPL, c4_setup);
+    if (!ndev)
+    {
+        printk (KERN_WARNING "%s: no memory for struct net_device !\n", hi->devname);
+        error_flag = ENOMEM;
+        return 0;
+    }
+    ci = (ci_t *)(netdev_priv(ndev));
+    ndev->irq = irq0;
+
+    ci->hdw_info = hi;
+    ci->state = C_INIT;         /* mark as hardware not available */
+    ci->next = c4_list;
+    c4_list = ci;
+    ci->brdno = ci->next ? ci->next->brdno + 1 : 0;
+
+    if (CI == 0)
+        CI = ci;                    /* DEBUG, only board 0 usage */
+
+    strcpy (ci->devname, hi->devname);
+    ci->release = &pmcc4_OSSI_release[0];
+
+    /* tasklet */
+#if defined(SBE_ISR_TASKLET)
+    tasklet_init (&ci->ci_musycc_isr_tasklet,
+                  (void (*) (unsigned long)) musycc_intr_bh_tasklet,
+                  (unsigned long) ci);
+
+    if (atomic_read (&ci->ci_musycc_isr_tasklet.count) == 0)
+        tasklet_disable_nosync (&ci->ci_musycc_isr_tasklet);
+#elif defined(SBE_ISR_IMMEDIATE)
+    ci->ci_musycc_isr_tq.routine = (void *) (unsigned long) musycc_intr_bh_tasklet;
+    ci->ci_musycc_isr_tq.data = ci;
+#endif
+
+
+    if (register_netdev (ndev) ||
+        (c4_init (ci, (u_char *) f0, (u_char *) f1) != SBE_DRVR_SUCCESS))
+    {
+        OS_kfree (netdev_priv(ndev));
+        OS_kfree (ndev);
+        error_flag = ENODEV;
+        return 0;
+    }
+    /*************************************************************
+     *  int request_irq(unsigned int irq,
+     *                  void (*handler)(int, void *, struct pt_regs *),
+     *                  unsigned long flags, const char *dev_name, void *dev_id);
+     *  wherein:
+     *  irq      -> The interrupt number that is being requested.
+     *  handler  -> Pointer to handling function being installed.
+     *  flags    -> A bit mask of options related to interrupt management.
+     *  dev_name -> String used in /proc/interrupts to show owner of interrupt.
+     *  dev_id   -> Pointer (for shared interrupt lines) to point to its own
+     *              private data area (to identify which device is interrupting).
+     *
+     *  extern void free_irq(unsigned int irq, void *dev_id);
+     **************************************************************/
+
+    if (request_irq (irq0, &c4_linux_interrupt,
+#if defined(SBE_ISR_TASKLET)
+                     IRQF_DISABLED | IRQF_SHARED,
+#elif defined(SBE_ISR_IMMEDIATE)
+                     IRQF_DISABLED | IRQF_SHARED,
+#elif defined(SBE_ISR_INLINE)
+                     IRQF_SHARED,
+#endif
+                     ndev->name, ndev))
+    {
+        printk (KERN_WARNING "%s: MUSYCC could not get irq: %d\n",
+                ndev->name, irq0);
+        unregister_netdev (ndev);
+        OS_kfree (netdev_priv(ndev));
+        OS_kfree (ndev);
+        error_flag = EIO;
+        return 0;
+    }
+#ifdef CONFIG_SBE_PMCC4_NCOMM
+    if (request_irq (irq1, &c4_ebus_interrupt, IRQF_SHARED, ndev->name, ndev))
+    {
+        printk (KERN_WARNING "%s: EBUS could not get irq: %d\n",
+                hi->devname, irq1);
+        unregister_netdev (ndev);
+        free_irq (irq0, ndev);
+        OS_kfree (ndev->priv);
+        OS_kfree (ndev);
+        error_flag = EIO;
+        return 0;
+    }
+#endif
+
+    /* setup board identification information */
+
+    {
+        u_int32_t   tmp;
+
+        hdw_sn_get (hi, brdno);     /* also sets PROM format type (promfmt)
+                                     * for later usage */
+
+        switch (hi->promfmt)
+        {
+        case PROM_FORMAT_TYPE1:
+            memcpy (ndev->dev_addr, (FLD_TYPE1 *) (hi->mfg_info.pft1.Serial), 6);
+            memcpy (&tmp, (FLD_TYPE1 *) (hi->mfg_info.pft1.Id), 4);     /* unaligned data
+                                                                         * acquisition */
+            ci->brd_id = cpu_to_be32 (tmp);
+            break;
+        case PROM_FORMAT_TYPE2:
+            memcpy (ndev->dev_addr, (FLD_TYPE2 *) (hi->mfg_info.pft2.Serial), 6);
+            memcpy (&tmp, (FLD_TYPE2 *) (hi->mfg_info.pft2.Id), 4);     /* unaligned data
+                                                                         * acquisition */
+            ci->brd_id = cpu_to_be32 (tmp);
+            break;
+        default:
+            ci->brd_id = 0;
+            memset (ndev->dev_addr, 0, 6);
+            break;
+        }
+
+#if 1
+        sbeid_set_hdwbid (ci);      /* requires bid to be preset */
+#else
+        sbeid_set_bdtype (ci);      /* requires hdw_bid to be preset */
+#endif
+
+    }
+
+#ifdef CONFIG_PROC_FS
+    sbecom_proc_brd_init (ci);
+#endif
+#if defined(SBE_ISR_TASKLET)
+    tasklet_enable (&ci->ci_musycc_isr_tasklet);
+#endif
+
+
+    if ((error_flag = c4_init2 (ci)) != SBE_DRVR_SUCCESS)
+    {
+#ifdef CONFIG_PROC_FS
+        sbecom_proc_brd_cleanup (ci);
+#endif
+        unregister_netdev (ndev);
+        free_irq (irq1, ndev);
+        free_irq (irq0, ndev);
+        OS_kfree (netdev_priv(ndev));
+        OS_kfree (ndev);
+        return 0;                   /* failure, error_flag is set */
+    }
+    return ndev;
+}
+
+STATIC int  __init
+c4_mod_init (void)
+{
+    int         rtn;
+
+    printk (KERN_WARNING "%s: %s\n", THIS_MODULE->name, pmcc4_OSSI_release);
+    if ((rtn = c4hw_attach_all ()))
+        return -rtn;                /* installation failure - see system log */
+
+    /* housekeeping notifications */
+    if (log_level != log_level_default)
+        printk (KERN_INFO "%s NOTE: driver parameter <log_level> changed from default %d to %d.\n",
+                THIS_MODULE->name, log_level_default, log_level);
+    if (max_mru != max_mru_default)
+        printk (KERN_INFO "%s NOTE: driver parameter <max_mru> changed from default %d to %d.\n",
+                THIS_MODULE->name, max_mru_default, max_mru);
+    if (max_mtu != max_mtu_default)
+        printk (KERN_INFO "%s NOTE: driver parameter <max_mtu> changed from default %d to %d.\n",
+                THIS_MODULE->name, max_mtu_default, max_mtu);
+    if (max_rxdesc_used != max_rxdesc_default)
+    {
+        if (max_rxdesc_used > 2000)
+            max_rxdesc_used = 2000; /* out-of-bounds reset */
+        printk (KERN_INFO "%s NOTE: driver parameter <max_rxdesc_used> changed from default %d to %d.\n",
+                THIS_MODULE->name, max_rxdesc_default, max_rxdesc_used);
+    }
+    if (max_txdesc_used != max_txdesc_default)
+    {
+        if (max_txdesc_used > 1000)
+            max_txdesc_used = 1000; /* out-of-bounds reset */
+        printk (KERN_INFO "%s NOTE: driver parameter <max_txdesc_used> changed from default %d to %d.\n",
+                THIS_MODULE->name, max_txdesc_default, max_txdesc_used);
+    }
+    return 0;                       /* installation success */
+}
+
+
+ /*
+  * find any still allocated hdlc registrations and unregister via call to
+  * do_deluser()
+  */
+
+STATIC void __exit
+cleanup_hdlc (void)
+{
+    hdw_info_t *hi;
+    ci_t       *ci;
+    struct net_device *ndev;
+    int         i, j, k;
+
+    for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
+    {
+        if (hi->ndev)               /* a board has been attached */
+        {
+            ci = (ci_t *)(netdev_priv(hi->ndev));
+            for (j = 0; j < ci->max_port; j++)
+                for (k = 0; k < MUSYCC_NCHANS; k++)
+                    if ((ndev = ci->port[j].chan[k]->user))
+                    {
+                        do_deluser (ndev, 0);
+                    }
+        }
+    }
+}
+
+
+STATIC void __exit
+c4_mod_remove (void)
+{
+    cleanup_hdlc ();            /* delete any missed channels */
+    cleanup_devs ();
+    c4_cleanup ();
+    cleanup_ioremap ();
+    printk (KERN_INFO "SBE %s - driver removed.\n", THIS_MODULE->name);
+}
+
+module_init (c4_mod_init);
+module_exit (c4_mod_remove);
+
+#ifndef SBE_INCLUDE_SYMBOLS
+#ifndef CONFIG_SBE_WANC24_NCOMM
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+EXPORT_NO_SYMBOLS;
+#endif
+#endif
+#endif
+
+MODULE_AUTHOR ("SBE Technical Services <support@sbei.com>");
+MODULE_DESCRIPTION ("wanPCI-CxT1E1 Generic HDLC WAN Driver module");
+#ifdef MODULE_LICENSE
+MODULE_LICENSE ("GPL");
+#endif
+
+/***  End-of-File  ***/
diff --git a/drivers/staging/cxt1e1/musycc.c b/drivers/staging/cxt1e1/musycc.c
new file mode 100644 (file)
index 0000000..650c9c0
--- /dev/null
@@ -0,0 +1,2180 @@
+/*
+ * $Id: musycc.c,v 2.1 2007/08/15 23:32:17 rickd PMCC4_3_1B $
+ */
+
+unsigned int max_intcnt = 0;
+unsigned int max_bh = 0;
+
+/*-----------------------------------------------------------------------------
+ * musycc.c -
+ *
+ * Copyright (C) 2007  One Stop Systems, Inc.
+ * Copyright (C) 2003-2006  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@onestopsystems.com
+ * One Stop Systems, Inc.  Escondido, California  U.S.A.
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 2.1 $
+ * Last changed on $Date: 2007/08/15 23:32:17 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: musycc.c,v $
+ * Revision 2.1  2007/08/15 23:32:17  rickd
+ * Use 'if 0' instead of GNU comment delimeter to avoid line wrap induced compiler errors.
+ *
+ * Revision 2.0  2007/08/15 22:13:20  rickd
+ * Update to printf pointer %p usage and correct some UINT to ULONG for
+ * 64bit comptibility.
+ *
+ * Revision 1.7  2006/04/21 00:56:40  rickd
+ * workqueue files now prefixed with <sbecom> prefix.
+ *
+ * Revision 1.6  2005/10/27 18:54:19  rickd
+ * Clean out old code.  Default to HDLC_FCS16, not TRANS.
+ *
+ * Revision 1.5  2005/10/17 23:55:28  rickd
+ * Initial port of NCOMM support patches from original work found
+ * in pmc_c4t1e1 as updated by NCOMM.  Ref: CONFIG_SBE_PMCC4_NCOMM.
+ *
+ * Revision 1.4  2005/10/13 20:35:25  rickd
+ * Cleanup warning for unused <flags> variable.
+ *
+ * Revision 1.3  2005/10/13 19:19:22  rickd
+ * Disable redundant driver removal cleanup code.
+ *
+ * Revision 1.2  2005/10/11 18:36:16  rickd
+ * Clean up warning messages caused by de-implemented some <flags> associated
+ * with spin_lock() removals.
+ *
+ * Revision 1.1  2005/10/05 00:45:28  rickd
+ * Re-enable xmit on flow-controlled and full channel to fix restart hang.
+ * Add some temp spin-lock debug code (rld_spin_owner).
+ *
+ * Revision 1.0  2005/09/28 00:10:06  rickd
+ * Initial release for C4T1E1 support. Lots of transparent
+ * mode updates.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+char        SBEid_pmcc4_musyccc[] =
+"@(#)musycc.c - $Revision: 2.1 $      (c) Copyright 2004-2006 SBE, Inc.";
+
+
+#include <linux/types.h>
+#include "pmcc4_sysdep.h"
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include "sbecom_inline_linux.h"
+#include "libsbew.h"
+#include "pmcc4_private.h"
+#include "pmcc4.h"
+#include "musycc.h"
+
+#ifdef SBE_INCLUDE_SYMBOLS
+#define STATIC
+#else
+#define STATIC  static
+#endif
+
+#define sd_find_chan(ci,ch)   c4_find_chan(ch)
+
+
+/*******************************************************************/
+/* global driver variables */
+extern ci_t *c4_list;
+extern int  drvr_state;
+extern int  log_level;
+
+extern int  max_mru;
+extern int  max_mtu;
+extern int  max_rxdesc_used;
+extern int  max_txdesc_used;
+extern ci_t *CI;                /* dummy pointr to board ZEROE's data - DEBUG
+                                 * USAGE */
+
+
+/*******************************************************************/
+/* forward references */
+void        c4_fifo_free (mpi_t *, int);
+void        c4_wk_chan_restart (mch_t *);
+void        musycc_bh_tx_eom (mpi_t *, int);
+int         musycc_chan_up (ci_t *, int);
+status_t __init musycc_init (ci_t *);
+STATIC void __init musycc_init_port (mpi_t *);
+void        musycc_intr_bh_tasklet (ci_t *);
+void        musycc_serv_req (mpi_t *, u_int32_t);
+void        musycc_update_timeslots (mpi_t *);
+
+/*******************************************************************/
+
+#if 1
+STATIC int
+musycc_dump_rxbuffer_ring (mch_t * ch, int lockit)
+{
+    struct mdesc *m;
+    unsigned long flags = 0;
+
+    u_int32_t status;
+    int         n;
+
+    if (lockit)
+    {
+        spin_lock_irqsave (&ch->ch_rxlock, flags);
+    }
+    if (ch->rxd_num == 0)
+    {
+        printk ("  ZERO receive buffers allocated for this channel.");
+    } else
+    {
+        FLUSH_MEM_READ ();
+        m = &ch->mdr[ch->rxix_irq_srv];
+        for (n = ch->rxd_num; n; n--)
+        {
+            status = le32_to_cpu (m->status);
+            {
+                printk ("%c  %08lx[%2d]: sts %08x (%c%c%c%c:%d.) Data [%08x] Next [%08x]\n",
+                        (m == &ch->mdr[ch->rxix_irq_srv]) ? 'F' : ' ',
+                        (unsigned long) m, n,
+                        status,
+                        m->data ? (status & HOST_RX_OWNED ? 'H' : 'M') : '-',
+                        status & POLL_DISABLED ? 'P' : '-',
+                        status & EOBIRQ_ENABLE ? 'b' : '-',
+                        status & EOMIRQ_ENABLE ? 'm' : '-',
+                        status & LENGTH_MASK,
+                        le32_to_cpu (m->data), le32_to_cpu (m->next));
+#ifdef RLD_DUMP_BUFDATA
+                {
+                    u_int32_t  *dp;
+                    int         len = status & LENGTH_MASK;
+
+#if 1
+                    if (m->data && (status & HOST_RX_OWNED))
+#else
+                    if (m->data)    /* always dump regardless of valid RX
+                                     * data */
+#endif
+                    {
+                        dp = (u_int32_t *) OS_phystov ((void *) (le32_to_cpu (m->data)));
+                        if (len >= 0x10)
+                            printk ("    %x[%x]: %08X %08X %08X %08x\n", (u_int32_t) dp, len,
+                                    *dp, *(dp + 1), *(dp + 2), *(dp + 3));
+                        else if (len >= 0x08)
+                            printk ("    %x[%x]: %08X %08X\n", (u_int32_t) dp, len,
+                                    *dp, *(dp + 1));
+                        else
+                            printk ("    %x[%x]: %08X\n", (u_int32_t) dp, len, *dp);
+                    }
+                }
+#endif
+            }
+            m = m->snext;
+        }
+    }                               /* -for- */
+    printk ("\n");
+
+    if (lockit)
+    {
+        spin_unlock_irqrestore (&ch->ch_rxlock, flags);
+    }
+    return 0;
+}
+#endif
+
+#if 1
+STATIC int
+musycc_dump_txbuffer_ring (mch_t * ch, int lockit)
+{
+    struct mdesc *m;
+    unsigned long flags = 0;
+    u_int32_t   status;
+    int         n;
+
+    if (lockit)
+    {
+        spin_lock_irqsave (&ch->ch_txlock, flags);
+    }
+    if (ch->txd_num == 0)
+    {
+        printk ("  ZERO transmit buffers allocated for this channel.");
+    } else
+    {
+        FLUSH_MEM_READ ();
+        m = ch->txd_irq_srv;
+        for (n = ch->txd_num; n; n--)
+        {
+            status = le32_to_cpu (m->status);
+            {
+                printk ("%c%c %08lx[%2d]: sts %08x (%c%c%c%c:%d.) Data [%08x] Next [%08x]\n",
+                        (m == ch->txd_usr_add) ? 'F' : ' ',
+                        (m == ch->txd_irq_srv) ? 'L' : ' ',
+                        (unsigned long) m, n,
+                        status,
+                     m->data ? (status & MUSYCC_TX_OWNED ? 'M' : 'H') : '-',
+                        status & POLL_DISABLED ? 'P' : '-',
+                        status & EOBIRQ_ENABLE ? 'b' : '-',
+                        status & EOMIRQ_ENABLE ? 'm' : '-',
+                        status & LENGTH_MASK,
+                        le32_to_cpu (m->data), le32_to_cpu (m->next));
+#ifdef RLD_DUMP_BUFDATA
+                {
+                    u_int32_t  *dp;
+                    int         len = status & LENGTH_MASK;
+
+                    if (m->data)
+                    {
+                        dp = (u_int32_t *) OS_phystov ((void *) (le32_to_cpu (m->data)));
+                        if (len >= 0x10)
+                            printk ("    %x[%x]: %08X %08X %08X %08x\n", (u_int32_t) dp, len,
+                                    *dp, *(dp + 1), *(dp + 2), *(dp + 3));
+                        else if (len >= 0x08)
+                            printk ("    %x[%x]: %08X %08X\n", (u_int32_t) dp, len,
+                                    *dp, *(dp + 1));
+                        else
+                            printk ("    %x[%x]: %08X\n", (u_int32_t) dp, len, *dp);
+                    }
+                }
+#endif
+            }
+            m = m->snext;
+        }
+    }                               /* -for- */
+    printk ("\n");
+
+    if (lockit)
+    {
+        spin_unlock_irqrestore (&ch->ch_txlock, flags);
+    }
+    return 0;
+}
+#endif
+
+
+/*
+ * The following supports a backdoor debug facility which can be used to
+ * display the state of a board's channel.
+ */
+
+status_t
+musycc_dump_ring (ci_t * ci, unsigned int chan)
+{
+    mch_t      *ch;
+
+    if (chan >= MAX_CHANS_USED)
+    {
+        return SBE_DRVR_FAIL;       /* E2BIG */
+    }
+    {
+        int         bh;
+
+        bh = atomic_read (&ci->bh_pending);
+        printk (">> bh_pend %d [%d] ihead %d itail %d [%d] th_cnt %d bh_cnt %d wdcnt %d note %d\n",
+                bh, max_bh, ci->iqp_headx, ci->iqp_tailx, max_intcnt,
+                ci->intlog.drvr_intr_thcount,
+                ci->intlog.drvr_intr_bhcount,
+                ci->wdcount, ci->wd_notify);
+        max_bh = 0;                 /* reset counter */
+        max_intcnt = 0;             /* reset counter */
+    }
+
+    if (!(ch = sd_find_chan (dummy, chan)))
+    {
+        printk (">> musycc_dump_ring: channel %d not up.\n", chan);
+        return ENOENT;
+    }
+    printk (">> CI %p CHANNEL %3d @ %p: state %x status/p %x/%x\n", ci, chan, ch, ch->state,
+            ch->status, ch->p.status);
+    printk ("--------------------------------\nTX Buffer Ring - Channel %d, txd_num %d. (bd/ch pend %d %d), TXD required %d, txpkt %lu\n",
+            chan, ch->txd_num,
+            (u_int32_t) atomic_read (&ci->tx_pending), (u_int32_t) atomic_read (&ch->tx_pending), ch->txd_required, ch->s.tx_packets);
+    printk ("++ User 0x%p IRQ_SRV 0x%p USR_ADD 0x%p QStopped %x, start_tx %x tx_full %d txd_free %d mode %x\n",
+            ch->user, ch->txd_irq_srv, ch->txd_usr_add,
+            sd_queue_stopped (ch->user),
+            ch->ch_start_tx, ch->tx_full, ch->txd_free, ch->p.chan_mode);
+    musycc_dump_txbuffer_ring (ch, 1);
+    printk ("RX Buffer Ring - Channel %d, rxd_num %d. IRQ_SRV[%d] 0x%p, start_rx %x rxpkt %lu\n",
+            chan, ch->rxd_num, ch->rxix_irq_srv,
+            &ch->mdr[ch->rxix_irq_srv], ch->ch_start_rx, ch->s.rx_packets);
+    musycc_dump_rxbuffer_ring (ch, 1);
+
+    return SBE_DRVR_SUCCESS;
+}
+
+
+status_t
+musycc_dump_rings (ci_t * ci, unsigned int start_chan)
+{
+    unsigned int chan;
+
+    for (chan = start_chan; chan < (start_chan + 5); chan++)
+        musycc_dump_ring (ci, chan);
+    return SBE_DRVR_SUCCESS;
+}
+
+
+/*
+ * NOTE on musycc_init_mdt():  These MUSYCC writes are only operational after
+ * a MUSYCC GROUP_INIT command has been issued.
+ */
+
+void
+musycc_init_mdt (mpi_t * pi)
+{
+    u_int32_t  *addr, cfg;
+    int         i;
+
+    /*
+     * This Idle Code insertion takes effect prior to channel's first
+     * transmitted  message.  After that, each message contains its own Idle
+     * Code information which is to be issued after the message is
+     * transmitted (Ref.MUSYCC 5.2.2.3: MCENBL bit in Group Configuration
+     * Descriptor).
+     */
+
+    addr = (u_int32_t *) ((u_long) pi->reg + MUSYCC_MDT_BASE03_ADDR);
+    cfg = CFG_CH_FLAG_7E << IDLE_CODE;
+
+    for (i = 0; i < 32; addr++, i++)
+    {
+        pci_write_32 (addr, cfg);
+    }
+}
+
+
+/* Set TX thp to the next unprocessed md */
+
+void
+musycc_update_tx_thp (mch_t * ch)
+{
+    struct mdesc *md;
+    unsigned long flags;
+
+    spin_lock_irqsave (&ch->ch_txlock, flags);
+    while (1)
+    {
+        md = ch->txd_irq_srv;
+        FLUSH_MEM_READ ();
+        if (!md->data)
+        {
+            /* No MDs with buffers to process */
+            spin_unlock_irqrestore (&ch->ch_txlock, flags);
+            return;
+        }
+        if ((le32_to_cpu (md->status)) & MUSYCC_TX_OWNED)
+        {
+            /* this is the MD to restart TX with */
+            break;
+        }
+        /*
+         * Otherwise, we have a valid, host-owned message descriptor which
+         * has been successfully transmitted and whose buffer can be freed,
+         * so... process this MD, it's owned by the host.  (This might give
+         * as a new, updated txd_irq_srv.)
+         */
+        musycc_bh_tx_eom (ch->up, ch->gchan);
+    }
+    md = ch->txd_irq_srv;
+    ch->up->regram->thp[ch->gchan] = cpu_to_le32 (OS_vtophys (md));
+    FLUSH_MEM_WRITE ();
+
+    if (ch->tx_full)
+    {
+        ch->tx_full = 0;
+        ch->txd_required = 0;
+        sd_enable_xmit (ch->user);  /* re-enable to catch flow controlled
+                                     * channel */
+    }
+    spin_unlock_irqrestore (&ch->ch_txlock, flags);
+
+#ifdef RLD_TRANS_DEBUG
+    printk ("++ musycc_update_tx_thp[%d]: setting thp = %p, sts %x\n", ch->channum, md, md->status);
+#endif
+}
+
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
+/*
+ * This is the workq task executed by the OS when our queue_work() is
+ * scheduled and run.  It can fire off either RX or TX ACTIVATION depending
+ * upon the channel's ch_start_tx and ch_start_rx variables.  This routine
+ * is implemented as a work queue so that the call to the service request is
+ * able to sleep, awaiting an interrupt acknowledgment response (SACK) from
+ * the hardware.
+ */
+
+void
+musycc_wq_chan_restart (void *arg)      /* channel private structure */
+{
+    mch_t      *ch;
+    mpi_t      *pi;
+    struct mdesc *md;
+#if 0
+    unsigned long flags;
+#endif
+
+    ch = container_of(arg, struct c4_chan_info, ch_work);
+    pi = ch->up;
+
+#ifdef RLD_TRANS_DEBUG
+    printk ("wq_chan_restart[%d]: start_RT[%d/%d] status %x\n",
+            ch->channum, ch->ch_start_rx, ch->ch_start_tx, ch->status);
+
+#endif
+
+    /**********************************/
+    /** check for RX restart request **/
+    /**********************************/
+
+    if ((ch->ch_start_rx) && (ch->status & RX_ENABLED))
+    {
+
+        ch->ch_start_rx = 0;
+#if defined(RLD_TRANS_DEBUG) || defined(RLD_RXACT_DEBUG)
+        {
+            static int  hereb4 = 7;
+
+            if (hereb4)             /* RLD DEBUG */
+            {
+                hereb4--;
+#ifdef RLD_TRANS_DEBUG
+                md = &ch->mdr[ch->rxix_irq_srv];
+                printk ("++ musycc_wq_chan_restart[%d] CHAN RX ACTIVATE: rxix_irq_srv %d, md %p sts %x, rxpkt %lu\n",
+                ch->channum, ch->rxix_irq_srv, md, le32_to_cpu (md->status),
+                        ch->s.rx_packets);
+#elif defined(RLD_RXACT_DEBUG)
+                md = &ch->mdr[ch->rxix_irq_srv];
+                printk ("++ musycc_wq_chan_restart[%d] CHAN RX ACTIVATE: rxix_irq_srv %d, md %p sts %x, rxpkt %lu\n",
+                ch->channum, ch->rxix_irq_srv, md, le32_to_cpu (md->status),
+                        ch->s.rx_packets);
+                musycc_dump_rxbuffer_ring (ch, 1);      /* RLD DEBUG */
+#endif
+            }
+        }
+#endif
+        musycc_serv_req (pi, SR_CHANNEL_ACTIVATE | SR_RX_DIRECTION | ch->gchan);
+    }
+    /**********************************/
+    /** check for TX restart request **/
+    /**********************************/
+
+    if ((ch->ch_start_tx) && (ch->status & TX_ENABLED))
+    {
+        /* find next unprocessed message, then set TX thp to it */
+        musycc_update_tx_thp (ch);
+
+#if 0
+        spin_lock_irqsave (&ch->ch_txlock, flags);
+#endif
+        md = ch->txd_irq_srv;
+        if (!md)
+        {
+#ifdef RLD_TRANS_DEBUG
+            printk ("-- musycc_wq_chan_restart[%d]: WARNING, starting NULL md\n", ch->channum);
+#endif
+#if 0
+            spin_unlock_irqrestore (&ch->ch_txlock, flags);
+#endif
+        } else if (md->data && ((le32_to_cpu (md->status)) & MUSYCC_TX_OWNED))
+        {
+            ch->ch_start_tx = 0;
+#if 0
+            spin_unlock_irqrestore (&ch->ch_txlock, flags);   /* allow interrupts for service request */
+#endif
+#ifdef RLD_TRANS_DEBUG
+            printk ("++ musycc_wq_chan_restart() CHAN TX ACTIVATE: chan %d txd_irq_srv %p = sts %x, txpkt %lu\n",
+                    ch->channum, ch->txd_irq_srv, ch->txd_irq_srv->status, ch->s.tx_packets);
+#endif
+            musycc_serv_req (pi, SR_CHANNEL_ACTIVATE | SR_TX_DIRECTION | ch->gchan);
+        }
+#ifdef RLD_RESTART_DEBUG
+        else
+        {
+            /* retain request to start until retried and we have data to xmit */
+            printk ("-- musycc_wq_chan_restart[%d]: DELAYED due to md %p sts %x data %x, start_tx %x\n",
+                    ch->channum, md,
+                    le32_to_cpu (md->status),
+                    le32_to_cpu (md->data), ch->ch_start_tx);
+            musycc_dump_txbuffer_ring (ch, 0);
+#if 0
+            spin_unlock_irqrestore (&ch->ch_txlock, flags);   /* allow interrupts for service request */
+#endif
+        }
+#endif
+    }
+}
+#endif
+
+
+ /*
+  * Channel restart either fires of a workqueue request (2.6) or lodges a
+  * watchdog activation sequence (2.4).
+  */
+
+void
+musycc_chan_restart (mch_t * ch)
+{
+#ifdef RLD_RESTART_DEBUG
+    printk ("++ musycc_chan_restart[%d]: txd_irq_srv @ %p = sts %x\n",
+            ch->channum, ch->txd_irq_srv, ch->txd_irq_srv->status);
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
+    /* 2.6 - find next unprocessed message, then set TX thp to it */
+#ifdef RLD_RESTART_DEBUG
+    printk (">> musycc_chan_restart: scheduling Chan %x workQ @ %p\n", ch->channum, &ch->ch_work);
+#endif
+    c4_wk_chan_restart (ch);        /* work queue mechanism fires off: Ref:
+                                     * musycc_wq_chan_restart () */
+
+#else
+
+
+    /* 2.4 - find next unprocessed message, then set TX thp to it */
+#ifdef RLD_RESTART_DEBUG
+    printk (">> musycc_chan_restart: scheduling Chan %x start_tx %x\n", ch->channum, ch->ch_start_tx);
+#endif
+    /* restart transmission from background loop */
+    ch->up->up->wd_notify = WD_NOTIFY_1TX;
+#endif
+}
+
+
+#if 0
+void
+musycc_cleanup (ci_t * ci)
+{
+    mpi_t      *pi;
+    int         i, j;
+
+    /* free up driver resources */
+    ci->state = C_INIT;             /* mark as hardware not available */
+
+    for (i = 0; i < ci->max_ports; i++)
+    {
+        pi = &ci->port[i];
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
+        c4_wq_port_cleanup (pi);
+#endif
+        for (j = 0; j < MUSYCC_NCHANS; j++)
+        {
+            if (pi->chan[j])
+                OS_kfree (pi->chan[j]); /* free mch_t struct */
+        }
+        OS_kfree (pi->regram_saved);
+    }
+#if 0
+    /* obsolete - watchdog is now static w/in ci_t */
+    OS_free_watchdog (ci->wd);
+#endif
+    OS_kfree (ci->iqd_p_saved);
+    OS_kfree (ci);
+}
+#endif
+
+void
+rld_put_led (mpi_t * pi, u_int32_t ledval)
+{
+    static u_int32_t led = 0;
+
+    if (ledval == 0)
+        led = 0;
+    else
+        led |= ledval;
+
+    pci_write_32 ((u_int32_t *) &pi->up->cpldbase->leds, led);  /* RLD DEBUG TRANHANG */
+}
+
+
+#define MUSYCC_SR_RETRY_CNT  9
+
+void
+musycc_serv_req (mpi_t * pi, u_int32_t req)
+{
+    volatile u_int32_t r;
+    int         rcnt;
+
+    /*
+     * PORT NOTE: Semaphore protect service loop guarantees only a single
+     * operation at a time.  Per MUSYCC Manual - "Issuing service requests to
+     * the same channel group without first receiving ACK from each request
+     * may cause the host to lose track of which service request has been
+     * acknowledged."
+     */
+
+    SD_SEM_TAKE (&pi->sr_sem_busy, "serv");     /* only 1 thru here, per
+                                                 * group */
+
+    if (pi->sr_last == req)
+    {
+#ifdef RLD_TRANS_DEBUG
+        printk (">> same SR, Port %d Req %x\n", pi->portnum, req);
+#endif
+
+        /*
+         * The most likely repeated request is the channel activation command
+         * which follows the occurrence of a Transparent mode TX ONR or a
+         * BUFF error.  If the previous command was a CHANNEL ACTIVATE,
+         * precede it with a NOOP command in order maintain coherent control
+         * of this current (re)ACTIVATE.
+         */
+
+        r = (pi->sr_last & ~SR_GCHANNEL_MASK);
+        if ((r == (SR_CHANNEL_ACTIVATE | SR_TX_DIRECTION)) ||
+            (r == (SR_CHANNEL_ACTIVATE | SR_RX_DIRECTION)))
+        {
+#ifdef RLD_TRANS_DEBUG
+            printk (">> same CHAN ACT SR, Port %d Req %x => issue SR_NOOP CMD\n", pi->portnum, req);
+#endif
+            SD_SEM_GIVE (&pi->sr_sem_busy);     /* allow this next request */
+            musycc_serv_req (pi, SR_NOOP);
+            SD_SEM_TAKE (&pi->sr_sem_busy, "serv");     /* relock & continue w/
+                                                         * original req */
+        } else if (req == SR_NOOP)
+        {
+            /* no need to issue back-to-back SR_NOOP commands at this time */
+#ifdef RLD_TRANS_DEBUG
+            printk (">> same Port SR_NOOP skipped, Port %d\n", pi->portnum);
+#endif
+            SD_SEM_GIVE (&pi->sr_sem_busy);     /* allow this next request */
+            return;
+        }
+    }
+    rcnt = 0;
+    pi->sr_last = req;
+rewrite:
+    pci_write_32 ((u_int32_t *) &pi->reg->srd, req);
+    FLUSH_MEM_WRITE ();
+
+    /*
+     * Per MUSYCC Manual, Section 6.1,2 - "When writing an SCR service
+     * request, the host must ensure at least one PCI bus clock cycle has
+     * elapsed before writing another service request.  To meet this minimum
+     * elapsed service request write timing interval, it is recommended that
+     * the host follow any SCR write with another operation which reads from
+     * the same address."
+     */
+    r = pci_read_32 ((u_int32_t *) &pi->reg->srd);      /* adhere to write
+                                                         * timing imposition */
+
+
+    if ((r != req) && (req != SR_CHIP_RESET) && (++rcnt <= MUSYCC_SR_RETRY_CNT))
+    {
+        if (log_level >= LOG_MONITOR)
+            printk ("%s: %d - reissue srv req/last %x/%x (hdw reads %x), Chan %d.\n",
+                    pi->up->devname, rcnt, req, pi->sr_last, r,
+                    (pi->portnum * MUSYCC_NCHANS) + (req & 0x1f));
+        OS_uwait_dummy ();          /* this delay helps reduce reissue counts
+                                     * (reason not yet researched) */
+        goto rewrite;
+    }
+    if (rcnt > MUSYCC_SR_RETRY_CNT)
+    {
+        printk (KERN_WARNING "%s: failed service request (#%d)= %x, group %d.\n",
+                pi->up->devname, MUSYCC_SR_RETRY_CNT, req, pi->portnum);
+        SD_SEM_GIVE (&pi->sr_sem_busy); /* allow any next request */
+        return;
+    }
+    if (req == SR_CHIP_RESET)
+    {
+        /*
+         * PORT NOTE: the CHIP_RESET command is NOT ack'd by the MUSYCC, thus
+         * the upcoming delay is used.  Though the MUSYCC documentation
+         * suggests a read-after-write would supply the required delay, it's
+         * unclear what CPU/BUS clock speeds might have been assumed when
+         * suggesting this 'lack of ACK' workaround.  Thus the use of uwait.
+         */
+        OS_uwait (100000, "icard"); /* 100ms */
+    } else
+    {
+        FLUSH_MEM_READ ();
+        SD_SEM_TAKE (&pi->sr_sem_wait, "sakack");       /* sleep until SACK
+                                                         * interrupt occurs */
+    }
+    SD_SEM_GIVE (&pi->sr_sem_busy); /* allow any next request */
+}
+
+
+#ifdef  SBE_PMCC4_ENABLE
+void
+musycc_update_timeslots (mpi_t * pi)
+{
+    int         i, ch;
+    char        e1mode = IS_FRAME_ANY_E1 (pi->p.port_mode);
+
+    for (i = 0; i < 32; i++)
+    {
+        int         usedby = 0, last = 0, ts, j, bits[8];
+
+        u_int8_t lastval = 0;
+
+        if (((i == 0) && e1mode) || /* disable if  E1 mode */
+            ((i == 16) && ((pi->p.port_mode == CFG_FRAME_E1CRC_CAS) || (pi->p.port_mode == CFG_FRAME_E1CRC_CAS_AMI)))
+            || ((i > 23) && (!e1mode))) /* disable if T1 mode */
+        {
+            pi->tsm[i] = 0xff;      /* make tslot unavailable for this mode */
+        } else
+        {
+            pi->tsm[i] = 0x00;      /* make tslot available for assignment */
+        }
+        for (j = 0; j < 8; j++)
+            bits[j] = -1;
+        for (ch = 0; ch < MUSYCC_NCHANS; ch++)
+        {
+            if ((pi->chan[ch]->state == UP) && (pi->chan[ch]->p.bitmask[i]))
+            {
+                usedby++;
+                last = ch;
+                lastval = pi->chan[ch]->p.bitmask[i];
+                for (j = 0; j < 8; j++)
+                    if (lastval & (1 << j))
+                        bits[j] = ch;
+                pi->tsm[i] |= lastval;
+            }
+        }
+        if (!usedby)
+            ts = 0;
+        else if ((usedby == 1) && (lastval == 0xff))
+            ts = (4 << 5) | last;
+        else if ((usedby == 1) && (lastval == 0x7f))
+            ts = (5 << 5) | last;
+        else
+        {
+            int         idx;
+
+            if (bits[0] < 0)
+                ts = (6 << 5) | (idx = last);
+            else
+                ts = (7 << 5) | (idx = bits[0]);
+            for (j = 1; j < 8; j++)
+            {
+                pi->regram->rscm[idx * 8 + j] = (bits[j] < 0) ? 0 : (0x80 | bits[j]);
+                pi->regram->tscm[idx * 8 + j] = (bits[j] < 0) ? 0 : (0x80 | bits[j]);
+            }
+        }
+        pi->regram->rtsm[i] = ts;
+        pi->regram->ttsm[i] = ts;
+    }
+    FLUSH_MEM_WRITE ();
+
+    musycc_serv_req (pi, SR_TIMESLOT_MAP | SR_RX_DIRECTION);
+    musycc_serv_req (pi, SR_TIMESLOT_MAP | SR_TX_DIRECTION);
+    musycc_serv_req (pi, SR_SUBCHANNEL_MAP | SR_RX_DIRECTION);
+    musycc_serv_req (pi, SR_SUBCHANNEL_MAP | SR_TX_DIRECTION);
+}
+#endif
+
+
+#ifdef SBE_WAN256T3_ENABLE
+void
+musycc_update_timeslots (mpi_t * pi)
+{
+    mch_t      *ch;
+
+    u_int8_t    ts, hmask, tsen;
+    int         gchan;
+    int         i;
+
+#ifdef SBE_PMCC4_ENABLE
+    hmask = (0x1f << pi->up->p.hypersize) & 0x1f;
+#endif
+#ifdef SBE_WAN256T3_ENABLE
+    hmask = (0x1f << hyperdummy) & 0x1f;
+#endif
+    for (i = 0; i < 128; i++)
+    {
+        gchan = ((pi->portnum * MUSYCC_NCHANS) + (i & hmask)) % MUSYCC_NCHANS;
+        ch = pi->chan[gchan];
+        if (ch->p.mode_56k)
+            tsen = MODE_56KBPS;
+        else
+            tsen = MODE_64KBPS;     /* also the default */
+        ts = ((pi->portnum % 4) == (i / 32)) ? (tsen << 5) | (i & hmask) : 0;
+        pi->regram->rtsm[i] = ts;
+        pi->regram->ttsm[i] = ts;
+    }
+    FLUSH_MEM_WRITE ();
+    musycc_serv_req (pi, SR_TIMESLOT_MAP | SR_RX_DIRECTION);
+    musycc_serv_req (pi, SR_TIMESLOT_MAP | SR_TX_DIRECTION);
+}
+#endif
+
+
+ /*
+  * This routine converts a generic library channel configuration parameter
+  * into a hardware specific register value (IE. MUSYCC CCD Register).
+  */
+u_int32_t
+musycc_chan_proto (int proto)
+{
+    int         reg;
+
+    switch (proto)
+    {
+    case CFG_CH_PROTO_TRANS:        /* 0 */
+        reg = MUSYCC_CCD_TRANS;
+        break;
+    case CFG_CH_PROTO_SS7:          /* 1 */
+        reg = MUSYCC_CCD_SS7;
+        break;
+    default:
+    case CFG_CH_PROTO_ISLP_MODE:   /* 4 */
+    case CFG_CH_PROTO_HDLC_FCS16:  /* 2 */
+        reg = MUSYCC_CCD_HDLC_FCS16;
+        break;
+    case CFG_CH_PROTO_HDLC_FCS32:  /* 3 */
+        reg = MUSYCC_CCD_HDLC_FCS32;
+        break;
+    }
+
+    return reg;
+}
+
+#ifdef SBE_WAN256T3_ENABLE
+STATIC void __init
+musycc_init_port (mpi_t * pi)
+{
+    pci_write_32 ((u_int32_t *) &pi->reg->gbp, OS_vtophys (pi->regram));
+
+    pi->regram->grcd =
+        __constant_cpu_to_le32 (MUSYCC_GRCD_RX_ENABLE |
+                                MUSYCC_GRCD_TX_ENABLE |
+                                MUSYCC_GRCD_SF_ALIGN |
+                                MUSYCC_GRCD_SUBCHAN_DISABLE |
+                                MUSYCC_GRCD_OOFMP_DISABLE |
+                                MUSYCC_GRCD_COFAIRQ_DISABLE |
+                                MUSYCC_GRCD_MC_ENABLE |
+                       (MUSYCC_GRCD_POLLTH_32 << MUSYCC_GRCD_POLLTH_SHIFT));
+
+    pi->regram->pcd =
+        __constant_cpu_to_le32 (MUSYCC_PCD_E1X4_MODE |
+                                MUSYCC_PCD_TXDATA_RISING |
+                                MUSYCC_PCD_TX_DRIVEN);
+
+    /* Message length descriptor */
+    pi->regram->mld = __constant_cpu_to_le32 (max_mru | (max_mru << 16));
+    FLUSH_MEM_WRITE ();
+
+    musycc_serv_req (pi, SR_GROUP_INIT | SR_RX_DIRECTION);
+    musycc_serv_req (pi, SR_GROUP_INIT | SR_TX_DIRECTION);
+
+    musycc_init_mdt (pi);
+
+    musycc_update_timeslots (pi);
+}
+#endif
+
+
+status_t    __init
+musycc_init (ci_t * ci)
+{
+    char       *regaddr;        /* temp for address boundary calculations */
+    int         i, gchan;
+
+    OS_sem_init (&ci->sem_wdbusy, SEM_AVAILABLE);       /* watchdog exclusion */
+
+    /*
+     * Per MUSYCC manual, Section 6.3.4 - "The host must allocate a dword
+     * aligned memory segment for interrupt queue pointers."
+     */
+
+#define INT_QUEUE_BOUNDARY  4
+
+    regaddr = OS_kmalloc ((INT_QUEUE_SIZE + 1) * sizeof (u_int32_t));
+    if (regaddr == 0)
+        return ENOMEM;
+    ci->iqd_p_saved = regaddr;      /* save orig value for free's usage */
+    ci->iqd_p = (u_int32_t *) ((unsigned long) (regaddr + INT_QUEUE_BOUNDARY - 1) &
+                               (~(INT_QUEUE_BOUNDARY - 1)));    /* this calculates
+                                                                 * closest boundary */
+
+    for (i = 0; i < INT_QUEUE_SIZE; i++)
+    {
+        ci->iqd_p[i] = __constant_cpu_to_le32 (INT_EMPTY_ENTRY);
+    }
+
+    for (i = 0; i < ci->max_port; i++)
+    {
+        mpi_t      *pi = &ci->port[i];
+
+        /*
+         * Per MUSYCC manual, Section 6.3.2 - "The host must allocate a 2KB
+         * bound memory segment for Channel Group 0."
+         */
+
+#define GROUP_BOUNDARY   0x800
+
+        regaddr = OS_kmalloc (sizeof (struct musycc_groupr) + GROUP_BOUNDARY);
+        if (regaddr == 0)
+        {
+            for (gchan = 0; gchan < i; gchan++)
+            {
+                pi = &ci->port[gchan];
+                OS_kfree (pi->reg);
+                pi->reg = 0;
+            }
+            return ENOMEM;
+        }
+        pi->regram_saved = regaddr; /* save orig value for free's usage */
+        pi->regram = (struct musycc_groupr *) ((unsigned long) (regaddr + GROUP_BOUNDARY - 1) &
+                                               (~(GROUP_BOUNDARY - 1)));        /* this calculates
+                                                                                 * closest boundary */
+    }
+
+    /* any board centric MUSYCC commands will use group ZERO as its "home" */
+    ci->regram = ci->port[0].regram;
+    musycc_serv_req (&ci->port[0], SR_CHIP_RESET);
+
+    pci_write_32 ((u_int32_t *) &ci->reg->gbp, OS_vtophys (ci->regram));
+    pci_flush_write (ci);
+#ifdef CONFIG_SBE_PMCC4_NCOMM
+    ci->regram->__glcd = __constant_cpu_to_le32 (GCD_MAGIC);
+#else
+    /* standard driver POLLS for INTB via CPLD register */
+    ci->regram->__glcd = __constant_cpu_to_le32 (GCD_MAGIC | MUSYCC_GCD_INTB_DISABLE);
+#endif
+
+    ci->regram->__iqp = cpu_to_le32 (OS_vtophys (&ci->iqd_p[0]));
+    ci->regram->__iql = __constant_cpu_to_le32 (INT_QUEUE_SIZE - 1);
+    pci_write_32 ((u_int32_t *) &ci->reg->dacbp, 0);
+    FLUSH_MEM_WRITE ();
+
+    ci->state = C_RUNNING;          /* mark as full interrupt processing
+                                     * available */
+
+    musycc_serv_req (&ci->port[0], SR_GLOBAL_INIT);     /* FIRST INTERRUPT ! */
+
+    /* sanity check settable parameters */
+
+    if (max_mru > 0xffe)
+    {
+        printk (KERN_WARNING "%s: Maximum allowed MRU exceeded, resetting %d to %d.\n",
+                THIS_MODULE->name, max_mru, 0xffe);
+        max_mru = 0xffe;
+    }
+    if (max_mtu > 0xffe)
+    {
+        printk (KERN_WARNING "%s: Maximum allowed MTU exceeded, resetting %d to %d.\n",
+                THIS_MODULE->name, max_mtu, 0xffe);
+        max_mtu = 0xffe;
+    }
+#ifdef SBE_WAN256T3_ENABLE
+    for (i = 0; i < MUSYCC_NPORTS; i++)
+        musycc_init_port (&ci->port[i]);
+#endif
+
+    return SBE_DRVR_SUCCESS;        /* no error */
+}
+
+
+void
+musycc_bh_tx_eom (mpi_t * pi, int gchan)
+{
+    mch_t      *ch;
+    struct mdesc *md;
+
+#if 0
+#ifndef SBE_ISR_INLINE
+    unsigned long flags;
+
+#endif
+#endif
+    volatile u_int32_t status;
+
+    ch = pi->chan[gchan];
+    if (ch == 0 || ch->state != UP)
+    {
+        if (log_level >= LOG_ERROR)
+            printk ("%s: intr: xmit EOM on uninitialized channel %d\n", pi->up->devname, gchan);
+    }
+    if (ch == 0 || ch->mdt == 0)
+        return;                     /* note: mdt==0 implies a malloc()
+                                     * failure w/in chan_up() routine */
+
+#if 0
+#ifdef SBE_ISR_INLINE
+    spin_lock_irq (&ch->ch_txlock);
+#else
+    spin_lock_irqsave (&ch->ch_txlock, flags);
+#endif
+#endif
+    do
+    {
+        FLUSH_MEM_READ ();
+        md = ch->txd_irq_srv;
+        status = le32_to_cpu (md->status);
+
+        /*
+         * Note: Per MUSYCC Ref 6.4.9, the host does not poll a host-owned
+         * Transmit Buffer Descriptor during Transparent Mode.
+         */
+        if (status & MUSYCC_TX_OWNED)
+        {
+            int         readCount, loopCount;
+
+            /***********************************************************/
+            /* HW Bug Fix                                              */
+            /* ----------                                              */
+            /* Under certain PCI Bus loading conditions, the data      */
+            /* associated with an update of Shared Memory is delayed   */
+            /* relative to its PCI Interrupt.  This is caught when     */
+            /* the host determines it does not yet OWN the descriptor. */
+            /***********************************************************/
+
+            readCount = 0;
+            while (status & MUSYCC_TX_OWNED)
+            {
+                for (loopCount = 0; loopCount < 0x30; loopCount++)
+                    OS_uwait_dummy ();  /* use call to avoid optimization
+                                         * removal of dummy delay */
+                FLUSH_MEM_READ ();
+                status = le32_to_cpu (md->status);
+                if (readCount++ > 40)
+                    break;          /* don't wait any longer */
+            }
+            if (status & MUSYCC_TX_OWNED)
+            {
+                if (log_level >= LOG_MONITOR)
+                {
+                    printk ("%s: Port %d Chan %2d - unexpected TX msg ownership intr (md %p sts %x)\n",
+                     pi->up->devname, pi->portnum, ch->channum, md, status);
+                    printk ("++ User 0x%p IRQ_SRV 0x%p USR_ADD 0x%p QStopped %x, start_tx %x tx_full %d txd_free %d mode %x\n",
+                            ch->user, ch->txd_irq_srv, ch->txd_usr_add,
+                            sd_queue_stopped (ch->user),
+                            ch->ch_start_tx, ch->tx_full, ch->txd_free, ch->p.chan_mode);
+                    musycc_dump_txbuffer_ring (ch, 0);
+                }
+                break;              /* Not our mdesc, done */
+            } else
+            {
+                if (log_level >= LOG_MONITOR)
+                    printk ("%s: Port %d Chan %2d - recovered TX msg ownership [%d] (md %p sts %x)\n",
+                            pi->up->devname, pi->portnum, ch->channum, readCount, md, status);
+            }
+        }
+        ch->txd_irq_srv = md->snext;
+
+        md->data = 0;
+        if (md->mem_token != 0)
+        {
+            /* upcount channel */
+            atomic_sub (OS_mem_token_tlen (md->mem_token), &ch->tx_pending);
+            /* upcount card */
+            atomic_sub (OS_mem_token_tlen (md->mem_token), &pi->up->tx_pending);
+#ifdef SBE_WAN256T3_ENABLE
+            if (!atomic_read (&pi->up->tx_pending))
+                wan256t3_led (pi->up, LED_TX, 0);
+#endif
+
+#ifdef CONFIG_SBE_WAN256T3_NCOMM
+            /* callback that our packet was sent */
+            {
+                int         hdlcnum = (pi->portnum * 32 + gchan);
+
+                if (hdlcnum >= 228)
+                {
+                    if (nciProcess_TX_complete)
+                        (*nciProcess_TX_complete) (hdlcnum,
+                                                   getuserbychan (gchan));
+                }
+            }
+#endif                              /*** CONFIG_SBE_WAN256T3_NCOMM ***/
+
+            OS_mem_token_free_irq (md->mem_token);
+            md->mem_token = 0;
+        }
+        md->status = 0;
+#ifdef RLD_TXFULL_DEBUG
+        if (log_level >= LOG_MONITOR2)
+            printk ("~~ tx_eom: tx_full %x  txd_free %d -> %d\n", ch->tx_full, ch->txd_free, ch->txd_free + 1);
+#endif
+        ++ch->txd_free;
+        FLUSH_MEM_WRITE ();
+
+        if ((ch->p.chan_mode != CFG_CH_PROTO_TRANS) && (status & EOBIRQ_ENABLE))
+        {
+            if (log_level >= LOG_MONITOR)
+                printk ("%s: Mode (%x) incorrect EOB status (%x)\n",
+                        pi->up->devname, ch->p.chan_mode, status);
+            if ((status & EOMIRQ_ENABLE) == 0)
+                break;
+        }
+    }
+    while ((ch->p.chan_mode != CFG_CH_PROTO_TRANS) && ((status & EOMIRQ_ENABLE) == 0));
+    /*
+     * NOTE: (The above 'while' is coupled w/ previous 'do', way above.) Each
+     * Transparent data buffer has the EOB bit, and NOT the EOM bit, set and
+     * will furthermore have a separate IQD associated with each messages
+     * buffer.
+     */
+
+    FLUSH_MEM_READ ();
+    /*
+     * Smooth flow control hysterisis by maintaining task stoppage until half
+     * the available write buffers are available.
+     */
+    if (ch->tx_full && (ch->txd_free >= (ch->txd_num / 2)))
+    {
+        /*
+         * Then, only releave task stoppage if we actually have enough
+         * buffers to service the last requested packet.  It may require MORE
+         * than half the available!
+         */
+        if (ch->txd_free >= ch->txd_required)
+        {
+
+#ifdef RLD_TXFULL_DEBUG
+            if (log_level >= LOG_MONITOR2)
+                printk ("tx_eom[%d]: enable xmit tx_full no more, txd_free %d txd_num/2 %d\n",
+                        ch->channum,
+                        ch->txd_free, ch->txd_num / 2);
+#endif
+            ch->tx_full = 0;
+            ch->txd_required = 0;
+            sd_enable_xmit (ch->user);  /* re-enable to catch flow controlled
+                                         * channel */
+        }
+    }
+#ifdef RLD_TXFULL_DEBUG
+    else if (ch->tx_full)
+    {
+        if (log_level >= LOG_MONITOR2)
+            printk ("tx_eom[%d]: bypass TX enable though room available? (txd_free %d txd_num/2 %d)\n",
+                    ch->channum,
+                    ch->txd_free, ch->txd_num / 2);
+    }
+#endif
+
+    FLUSH_MEM_WRITE ();
+#if 0
+#ifdef SBE_ISR_INLINE
+    spin_unlock_irq (&ch->ch_txlock);
+#else
+    spin_unlock_irqrestore (&ch->ch_txlock, flags);
+#endif
+#endif
+}
+
+
+STATIC void
+musycc_bh_rx_eom (mpi_t * pi, int gchan)
+{
+    mch_t      *ch;
+    void       *m, *m2;
+    struct mdesc *md;
+    volatile u_int32_t status;
+    u_int32_t   error;
+
+    ch = pi->chan[gchan];
+    if (ch == 0 || ch->state != UP)
+    {
+        if (log_level > LOG_ERROR)
+            printk ("%s: intr: receive EOM on uninitialized channel %d\n", pi->up->devname, gchan);
+        return;
+    }
+    if (ch->mdr == 0)
+        return;                     /* can this happen ? */
+
+    for (;;)
+    {
+        FLUSH_MEM_READ ();
+        md = &ch->mdr[ch->rxix_irq_srv];
+        status = le32_to_cpu (md->status);
+        if (!(status & HOST_RX_OWNED))
+            break;                  /* Not our mdesc, done */
+        m = md->mem_token;
+        error = (status >> 16) & 0xf;
+        if (error == 0)
+        {
+#ifdef CONFIG_SBE_WAN256T3_NCOMM
+            int         hdlcnum = (pi->portnum * 32 + gchan);
+
+            /*
+             * if the packet number belongs to NCOMM, then send it to the TMS
+             * driver
+             */
+            if (hdlcnum >= 228)
+            {
+                if (nciProcess_RX_packet)
+                    (*nciProcess_RX_packet) (hdlcnum, status & 0x3fff, m, ch->user);
+            } else
+#endif                              /*** CONFIG_SBE_WAN256T3_NCOMM ***/
+
+            {
+                if ((m2 = OS_mem_token_alloc (max_mru)))
+                {
+                    /* substitute the mbuf+cluster */
+                    md->mem_token = m2;
+                    md->data = cpu_to_le32 (OS_vtophys (OS_mem_token_data (m2)));
+
+                    /* pass the received mbuf upward */
+                    sd_recv_consume (m, status & LENGTH_MASK, ch->user);
+                    ch->s.rx_packets++;
+                    ch->s.rx_bytes += status & LENGTH_MASK;
+                } else
+                {
+                    ch->s.rx_dropped++;
+                }
+            }
+        } else if (error == ERR_FCS)
+        {
+            ch->s.rx_crc_errors++;
+        } else if (error == ERR_ALIGN)
+        {
+            ch->s.rx_missed_errors++;
+        } else if (error == ERR_ABT)
+        {
+            ch->s.rx_missed_errors++;
+        } else if (error == ERR_LNG)
+        {
+            ch->s.rx_length_errors++;
+        } else if (error == ERR_SHT)
+        {
+            ch->s.rx_length_errors++;
+        }
+        FLUSH_MEM_WRITE ();
+        status = max_mru;
+        if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
+            status |= EOBIRQ_ENABLE;
+        md->status = cpu_to_le32 (status);
+
+        /* Check next mdesc in the ring */
+        if (++ch->rxix_irq_srv >= ch->rxd_num)
+            ch->rxix_irq_srv = 0;
+        FLUSH_MEM_WRITE ();
+    }
+}
+
+
+irqreturn_t
+musycc_intr_th_handler (void *devp)
+{
+    ci_t       *ci = (ci_t *) devp;
+    volatile u_int32_t status, currInt = 0;
+    u_int32_t   nextInt, intCnt;
+
+    /*
+     * Hardware not available, potential interrupt hang.  But since interrupt
+     * might be shared, just return.
+     */
+    if (ci->state == C_INIT)
+    {
+        return IRQ_NONE;
+    }
+    /*
+     * Marked as hardware available. Don't service interrupts, just clear the
+     * event.
+     */
+
+    if (ci->state == C_IDLE)
+    {
+        status = pci_read_32 ((u_int32_t *) &ci->reg->isd);
+
+        /* clear the interrupt but process nothing else */
+        pci_write_32 ((u_int32_t *) &ci->reg->isd, status);
+        return IRQ_HANDLED;
+    }
+    FLUSH_PCI_READ ();
+    FLUSH_MEM_READ ();
+
+    status = pci_read_32 ((u_int32_t *) &ci->reg->isd);
+    nextInt = INTRPTS_NEXTINT (status);
+    intCnt = INTRPTS_INTCNT (status);
+    ci->intlog.drvr_intr_thcount++;
+
+    /*********************************************************/
+    /* HW Bug Fix                                            */
+    /* ----------                                            */
+    /* Under certain PCI Bus loading conditions, the         */
+    /* MUSYCC looses the data associated with an update      */
+    /* of its ISD and erroneously returns the immediately    */
+    /* preceding 'nextInt' value.  However, the 'intCnt'     */
+    /* value appears to be correct.  By not starting service */
+    /* where the 'missing' 'nextInt' SHOULD point causes     */
+    /* the IQD not to be serviced - the 'not serviced'       */
+    /* entries then remain and continue to increase as more  */
+    /* incorrect ISD's are encountered.                      */
+    /*********************************************************/
+
+    if (nextInt != INTRPTS_NEXTINT (ci->intlog.this_status_new))
+    {
+        if (log_level >= LOG_MONITOR)
+        {
+            printk ("%s: note - updated ISD from %08x to %08x\n",
+                    ci->devname, status,
+              (status & (~INTRPTS_NEXTINT_M)) | ci->intlog.this_status_new);
+        }
+        /*
+         * Replace bogus status with software corrected value.
+         *
+         * It's not known whether, during this problem occurrence, if the
+         * INTFULL bit is correctly reported or not.
+         */
+        status = (status & (~INTRPTS_NEXTINT_M)) | (ci->intlog.this_status_new);
+        nextInt = INTRPTS_NEXTINT (status);
+    }
+    /**********************************************/
+    /* Cn847x Bug Fix                             */
+    /* --------------                             */
+    /* Fix for inability to write back same index */
+    /* as read for a full interrupt queue.        */
+    /**********************************************/
+
+    if (intCnt == INT_QUEUE_SIZE)
+    {
+        currInt = ((intCnt - 1) + nextInt) & (INT_QUEUE_SIZE - 1);
+    } else
+        /************************************************/
+        /* Interrupt Write Location Issues              */
+        /* -------------------------------              */
+        /* When the interrupt status descriptor is      */
+        /* written, the interrupt line is de-asserted   */
+        /* by the Cn847x.  In the case of MIPS          */
+        /* microprocessors, this must occur at the      */
+        /* beginning of the interrupt handler so that   */
+        /* the interrupt handle is not re-entered due   */
+        /* to interrupt dis-assertion latency.          */
+        /* In the case of all other processors, this    */
+        /* action should occur at the end of the        */
+        /* interrupt handler to avoid overwriting the   */
+        /* interrupt queue.                             */
+        /************************************************/
+
+    if (intCnt)
+    {
+        currInt = (intCnt + nextInt) & (INT_QUEUE_SIZE - 1);
+    } else
+    {
+        /*
+         * NOTE: Servicing an interrupt whose ISD contains a count of ZERO
+         * can be indicative of a Shared Interrupt chain.  Our driver can be
+         * called from the system's interrupt handler as a matter of the OS
+         * walking the chain.  As the chain is walked, the interrupt will
+         * eventually be serviced by the correct driver/handler.
+         */
+#if 0
+        /* chained interrupt = not ours */
+        printk (">> %s: intCnt NULL, sts %x, possibly a chained interrupt!\n",
+                ci->devname, status);
+#endif
+        return IRQ_NONE;
+    }
+
+    ci->iqp_tailx = currInt;
+
+    currInt <<= INTRPTS_NEXTINT_S;
+    ci->intlog.last_status_new = ci->intlog.this_status_new;
+    ci->intlog.this_status_new = currInt;
+
+    if ((log_level >= LOG_WARN) && (status & INTRPTS_INTFULL_M))
+    {
+        printk ("%s: Interrupt queue full condition occurred\n", ci->devname);
+    }
+    if (log_level >= LOG_DEBUG)
+        printk ("%s: interrupts pending, isd @ 0x%p: %x curr %d cnt %d NEXT %d\n",
+                ci->devname, &ci->reg->isd,
+        status, nextInt, intCnt, (intCnt + nextInt) & (INT_QUEUE_SIZE - 1));
+
+    FLUSH_MEM_WRITE ();
+#if defined(SBE_ISR_TASKLET)
+    pci_write_32 ((u_int32_t *) &ci->reg->isd, currInt);
+    atomic_inc (&ci->bh_pending);
+    tasklet_schedule (&ci->ci_musycc_isr_tasklet);
+#elif defined(SBE_ISR_IMMEDIATE)
+    pci_write_32 ((u_int32_t *) &ci->reg->isd, currInt);
+    atomic_inc (&ci->bh_pending);
+    queue_task (&ci->ci_musycc_isr_tq, &tq_immediate);
+    mark_bh (IMMEDIATE_BH);
+#elif defined(SBE_ISR_INLINE)
+    (void) musycc_intr_bh_tasklet (ci);
+    pci_write_32 ((u_int32_t *) &ci->reg->isd, currInt);
+#endif
+    return IRQ_HANDLED;
+}
+
+
+#if defined(SBE_ISR_IMMEDIATE)
+unsigned long
+#else
+void
+#endif
+musycc_intr_bh_tasklet (ci_t * ci)
+{
+    mpi_t      *pi;
+    mch_t      *ch;
+    unsigned int intCnt;
+    volatile u_int32_t currInt = 0;
+    volatile unsigned int headx, tailx;
+    int         readCount, loopCount;
+    int         group, gchan, event, err, tx;
+    u_int32_t   badInt = INT_EMPTY_ENTRY;
+    u_int32_t   badInt2 = INT_EMPTY_ENTRY2;
+
+    /*
+     * Hardware not available, potential interrupt hang.  But since interrupt
+     * might be shared, just return.
+     */
+    if ((drvr_state != SBE_DRVR_AVAILABLE) || (ci->state == C_INIT))
+    {
+#if defined(SBE_ISR_IMMEDIATE)
+        return 0L;
+#else
+        return;
+#endif
+    }
+#if defined(SBE_ISR_TASKLET) || defined(SBE_ISR_IMMEDIATE)
+    if (drvr_state != SBE_DRVR_AVAILABLE)
+    {
+#if defined(SBE_ISR_TASKLET)
+        return;
+#elif defined(SBE_ISR_IMMEDIATE)
+        return 0L;
+#endif
+    }
+#elif defined(SBE_ISR_INLINE)
+    /* no semaphore taken, no double checks */
+#endif
+
+    ci->intlog.drvr_intr_bhcount++;
+    FLUSH_MEM_READ ();
+    {
+        unsigned int bh = atomic_read (&ci->bh_pending);
+
+        max_bh = max (bh, max_bh);
+    }
+    atomic_set (&ci->bh_pending, 0);/* if here, no longer pending */
+    while ((headx = ci->iqp_headx) != (tailx = ci->iqp_tailx))
+    {
+        intCnt = (tailx >= headx) ? (tailx - headx) : (tailx - headx + INT_QUEUE_SIZE);
+        currInt = le32_to_cpu (ci->iqd_p[headx]);
+
+        max_intcnt = max (intCnt, max_intcnt);  /* RLD DEBUG */
+
+        /**************************************************/
+        /* HW Bug Fix                                     */
+        /* ----------                                     */
+        /* The following code checks for the condition    */
+        /* of interrupt assertion before interrupt        */
+        /* queue update.  This is a problem on several    */
+        /* PCI-Local bridge chips found on some products. */
+        /**************************************************/
+
+        readCount = 0;
+        if ((currInt == badInt) || (currInt == badInt2))
+            ci->intlog.drvr_int_failure++;
+
+        while ((currInt == badInt) || (currInt == badInt2))
+        {
+            for (loopCount = 0; loopCount < 0x30; loopCount++)
+                OS_uwait_dummy ();  /* use call to avoid optimization removal
+                                     * of dummy delay */
+            FLUSH_MEM_READ ();
+            currInt = le32_to_cpu (ci->iqd_p[headx]);
+            if (readCount++ > 20)
+                break;
+        }
+
+        if ((currInt == badInt) || (currInt == badInt2))        /* catch failure of Bug
+                                                                 * Fix checking */
+        {
+            if (log_level >= LOG_WARN)
+                printk ("%s: Illegal Interrupt Detected @ 0x%p, mod %d.)\n",
+                        ci->devname, &ci->iqd_p[headx], headx);
+
+            /*
+             * If the descriptor has not recovered, then leaving the EMPTY
+             * entry set will not signal to the MUSYCC that this descriptor
+             * has been serviced. The Interrupt Queue can then start loosing
+             * available descriptors and MUSYCC eventually encounters and
+             * reports the INTFULL condition.  Per manual, changing any bit
+             * marks descriptor as available, thus the use of different
+             * EMPTY_ENTRY values.
+             */
+
+            if (currInt == badInt)
+            {
+                ci->iqd_p[headx] = __constant_cpu_to_le32 (INT_EMPTY_ENTRY2);
+            } else
+            {
+                ci->iqd_p[headx] = __constant_cpu_to_le32 (INT_EMPTY_ENTRY);
+            }
+            ci->iqp_headx = (headx + 1) & (INT_QUEUE_SIZE - 1); /* insure wrapness */
+            FLUSH_MEM_WRITE ();
+            FLUSH_MEM_READ ();
+            continue;
+        }
+        group = INTRPT_GRP (currInt);
+        gchan = INTRPT_CH (currInt);
+        event = INTRPT_EVENT (currInt);
+        err = INTRPT_ERROR (currInt);
+        tx = currInt & INTRPT_DIR_M;
+
+        ci->iqd_p[headx] = __constant_cpu_to_le32 (INT_EMPTY_ENTRY);
+        FLUSH_MEM_WRITE ();
+
+        if (log_level >= LOG_DEBUG)
+        {
+            if (err != 0)
+                printk (" %08x -> err: %2d,", currInt, err);
+
+            printk ("+ interrupt event: %d, grp: %d, chan: %2d, side: %cX\n",
+                    event, group, gchan, tx ? 'T' : 'R');
+        }
+        pi = &ci->port[group];      /* notice that here we assume 1-1 group -
+                                     * port mapping */
+        ch = pi->chan[gchan];
+        switch (event)
+        {
+        case EVE_SACK:              /* Service Request Acknowledge */
+            if (log_level >= LOG_DEBUG)
+            {
+                volatile u_int32_t r;
+
+                r = pci_read_32 ((u_int32_t *) &pi->reg->srd);
+                printk ("- SACK cmd: %08x (hdw= %08x)\n", pi->sr_last, r);
+            }
+            SD_SEM_GIVE (&pi->sr_sem_wait);     /* wake up waiting process */
+            break;
+        case EVE_CHABT:     /* Change To Abort Code (0x7e -> 0xff) */
+        case EVE_CHIC:              /* Change To Idle Code (0xff -> 0x7e) */
+            break;
+        case EVE_EOM:               /* End Of Message */
+        case EVE_EOB:               /* End Of Buffer (Transparent mode) */
+            if (tx)
+            {
+                musycc_bh_tx_eom (pi, gchan);
+            } else
+            {
+                musycc_bh_rx_eom (pi, gchan);
+            }
+#if 0
+            break;
+#else
+            /*
+             * MUSYCC Interrupt Descriptor section states that EOB and EOM
+             * can be combined with the NONE error (as well as others).  So
+             * drop thru to catch this...
+             */
+#endif
+        case EVE_NONE:
+            if (err == ERR_SHT)
+            {
+                ch->s.rx_length_errors++;
+            }
+            break;
+        default:
+            if (log_level >= LOG_WARN)
+                printk ("%s: unexpected interrupt event: %d, iqd[%d]: %08x, port: %d\n", ci->devname,
+                        event, headx, currInt, group);
+            break;
+        }                           /* switch on event */
+
+
+        /*
+         * Per MUSYCC Manual, Section 6.4.8.3 [Transmit Errors], TX errors
+         * are service-affecting and require action to resume normal
+         * bit-level processing.
+         */
+
+        switch (err)
+        {
+        case ERR_ONR:
+            /*
+             * Per MUSYCC manual, Section  6.4.8.3 [Transmit Errors], this
+             * error requires Transmit channel reactivation.
+             *
+             * Per MUSYCC manual, Section  6.4.8.4 [Receive Errors], this error
+             * requires Receive channel reactivation.
+             */
+            if (tx)
+            {
+
+                /*
+                 * TX ONR Error only occurs when channel is configured for
+                 * Transparent Mode.  However, this code will catch and
+                 * re-activate on ANY TX ONR error.
+                 */
+
+                /*
+                 * Set flag to re-enable on any next transmit attempt.
+                 */
+                ch->ch_start_tx = CH_START_TX_ONR;
+
+                {
+#ifdef RLD_TRANS_DEBUG
+                    if (1 || log_level >= LOG_MONITOR)
+#else
+                    if (log_level >= LOG_MONITOR)
+#endif
+                    {
+                        printk ("%s: TX buffer underflow [ONR] on channel %d, mode %x QStopped %x free %d\n",
+                                ci->devname, ch->channum, ch->p.chan_mode, sd_queue_stopped (ch->user), ch->txd_free);
+#ifdef RLD_DEBUG
+                        if (ch->p.chan_mode == 2)       /* problem = ONR on HDLC
+                                                         * mode */
+                        {
+                            printk ("++ Failed Last %x Next %x QStopped %x, start_tx %x tx_full %d txd_free %d mode %x\n",
+                                    (u_int32_t) ch->txd_irq_srv, (u_int32_t) ch->txd_usr_add,
+                                    sd_queue_stopped (ch->user),
+                                    ch->ch_start_tx, ch->tx_full, ch->txd_free, ch->p.chan_mode);
+                            musycc_dump_txbuffer_ring (ch, 0);
+                        }
+#endif
+                    }
+                }
+            } else                  /* RX buffer overrun */
+            {
+                /*
+                 * Per MUSYCC manual, Section 6.4.8.4 [Receive Errors],
+                 * channel recovery for this RX ONR error IS required.  It is
+                 * also suggested to increase the number of receive buffers
+                 * for this channel.  Receive channel reactivation IS
+                 * required, and data has been lost.
+                 */
+                ch->s.rx_over_errors++;
+                ch->ch_start_rx = CH_START_RX_ONR;
+
+                if (log_level >= LOG_WARN)
+                {
+                    printk ("%s: RX buffer overflow [ONR] on channel %d, mode %x\n",
+                            ci->devname, ch->channum, ch->p.chan_mode);
+                    //musycc_dump_rxbuffer_ring (ch, 0);        /* RLD DEBUG */
+                }
+            }
+            musycc_chan_restart (ch);
+            break;
+        case ERR_BUF:
+            if (tx)
+            {
+                ch->s.tx_fifo_errors++;
+                ch->ch_start_tx = CH_START_TX_BUF;
+                /*
+                 * Per MUSYCC manual, Section  6.4.8.3 [Transmit Errors],
+                 * this BUFF error requires Transmit channel reactivation.
+                 */
+                if (log_level >= LOG_MONITOR)
+                    printk ("%s: TX buffer underrun [BUFF] on channel %d, mode %x\n",
+                            ci->devname, ch->channum, ch->p.chan_mode);
+            } else                  /* RX buffer overrun */
+            {
+                ch->s.rx_over_errors++;
+                /*
+                 * Per MUSYCC manual, Section 6.4.8.4 [Receive Errors], HDLC
+                 * mode requires NO recovery for this RX BUFF error is
+                 * required.  It is suggested to increase the FIFO buffer
+                 * space for this channel.  Receive channel reactivation is
+                 * not required, but data has been lost.
+                 */
+                if (log_level >= LOG_WARN)
+                    printk ("%s: RX buffer overrun [BUFF] on channel %d, mode %x\n",
+                            ci->devname, ch->channum, ch->p.chan_mode);
+                /*
+                 * Per MUSYCC manual, Section 6.4.9.4 [Receive Errors],
+                 * Transparent mode DOES require recovery for the RX BUFF
+                 * error.  It is suggested to increase the FIFO buffer space
+                 * for this channel.  Receive channel reactivation IS
+                 * required and data has been lost.
+                 */
+                if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
+                    ch->ch_start_rx = CH_START_RX_BUF;
+            }
+
+            if (tx || (ch->p.chan_mode == CFG_CH_PROTO_TRANS))
+                musycc_chan_restart (ch);
+            break;
+        default:
+            break;
+        }                           /* switch on err */
+
+        /* Check for interrupt lost condition */
+        if ((currInt & INTRPT_ILOST_M) && (log_level >= LOG_ERROR))
+        {
+            printk ("%s: Interrupt queue overflow - ILOST asserted\n",
+                    ci->devname);
+        }
+        ci->iqp_headx = (headx + 1) & (INT_QUEUE_SIZE - 1);     /* insure wrapness */
+        FLUSH_MEM_WRITE ();
+        FLUSH_MEM_READ ();
+    }                               /* while */
+    if ((log_level >= LOG_MONITOR2) && (ci->iqp_headx != ci->iqp_tailx))
+    {
+        int         bh;
+
+        bh = atomic_read (&CI->bh_pending);
+        printk ("_bh_: late arrivals, head %d != tail %d, pending %d\n",
+                ci->iqp_headx, ci->iqp_tailx, bh);
+    }
+#if defined(SBE_ISR_IMMEDIATE)
+    return 0L;
+#endif
+    /* else, nothing returned */
+}
+
+#if 0
+int         __init
+musycc_new_chan (ci_t * ci, int channum, void *user)
+{
+    mch_t      *ch;
+
+    ch = ci->port[channum / MUSYCC_NCHANS].chan[channum % MUSYCC_NCHANS];
+
+    if (ch->state != UNASSIGNED)
+        return EEXIST;
+    /* NOTE: mch_t already cleared during OS_kmalloc() */
+    ch->state = DOWN;
+    ch->user = user;
+#if 0
+    ch->status = 0;
+    ch->p.status = 0;
+    ch->p.intr_mask = 0;
+#endif
+    ch->p.chan_mode = CFG_CH_PROTO_HDLC_FCS16;
+    ch->p.idlecode = CFG_CH_FLAG_7E;
+    ch->p.pad_fill_count = 2;
+    spin_lock_init (&ch->ch_rxlock);
+    spin_lock_init (&ch->ch_txlock);
+
+    return 0;
+}
+#endif
+
+
+#ifdef SBE_PMCC4_ENABLE
+status_t
+musycc_chan_down (ci_t * dummy, int channum)
+{
+    mpi_t      *pi;
+    mch_t      *ch;
+    int         i, gchan;
+
+    if (!(ch = sd_find_chan (dummy, channum)))
+        return EINVAL;
+    pi = ch->up;
+    gchan = ch->gchan;
+
+    /* Deactivate the channel */
+    musycc_serv_req (pi, SR_CHANNEL_DEACTIVATE | SR_RX_DIRECTION | gchan);
+    ch->ch_start_rx = 0;
+    musycc_serv_req (pi, SR_CHANNEL_DEACTIVATE | SR_TX_DIRECTION | gchan);
+    ch->ch_start_tx = 0;
+
+    if (ch->state == DOWN)
+        return 0;
+    ch->state = DOWN;
+
+    pi->regram->thp[gchan] = 0;
+    pi->regram->tmp[gchan] = 0;
+    pi->regram->rhp[gchan] = 0;
+    pi->regram->rmp[gchan] = 0;
+    FLUSH_MEM_WRITE ();
+    for (i = 0; i < ch->txd_num; i++)
+    {
+        if (ch->mdt[i].mem_token != 0)
+            OS_mem_token_free (ch->mdt[i].mem_token);
+    }
+
+    for (i = 0; i < ch->rxd_num; i++)
+    {
+        if (ch->mdr[i].mem_token != 0)
+            OS_mem_token_free (ch->mdr[i].mem_token);
+    }
+
+    OS_kfree (ch->mdr);
+    ch->mdr = 0;
+    ch->rxd_num = 0;
+    OS_kfree (ch->mdt);
+    ch->mdt = 0;
+    ch->txd_num = 0;
+
+    musycc_update_timeslots (pi);
+    c4_fifo_free (pi, ch->gchan);
+
+    pi->openchans--;
+    return 0;
+}
+#endif
+
+
+int
+musycc_del_chan (ci_t * ci, int channum)
+{
+    mch_t      *ch;
+
+    if ((channum < 0) || (channum >= (MUSYCC_NPORTS * MUSYCC_NCHANS)))  /* sanity chk param */
+        return ECHRNG;
+    if (!(ch = sd_find_chan (ci, channum)))
+        return ENOENT;
+    if (ch->state == UP)
+        musycc_chan_down (ci, channum);
+    ch->state = UNASSIGNED;
+    return 0;
+}
+
+
+int
+musycc_del_chan_stats (ci_t * ci, int channum)
+{
+    mch_t      *ch;
+
+    if (channum < 0 || channum >= (MUSYCC_NPORTS * MUSYCC_NCHANS))      /* sanity chk param */
+        return ECHRNG;
+    if (!(ch = sd_find_chan (ci, channum)))
+        return ENOENT;
+
+    memset (&ch->s, 0, sizeof (struct sbecom_chan_stats));
+    return 0;
+}
+
+
+int
+musycc_start_xmit (ci_t * ci, int channum, void *mem_token)
+{
+    mch_t      *ch;
+    struct mdesc *md;
+    void       *m2;
+#if 0
+    unsigned long flags;
+#endif
+    int         txd_need_cnt;
+    u_int32_t   len;
+
+    if (!(ch = sd_find_chan (ci, channum)))
+        return ENOENT;
+
+    if (ci->state != C_RUNNING)     /* full interrupt processing available */
+        return EINVAL;
+    if (ch->state != UP)
+        return EINVAL;
+
+    if (!(ch->status & TX_ENABLED))
+        return EROFS;               /* how else to flag unwritable state ? */
+
+#ifdef RLD_TRANS_DEBUGx
+    if (1 || log_level >= LOG_MONITOR2)
+#else
+    if (log_level >= LOG_MONITOR2)
+#endif
+    {
+        printk ("++ start_xmt[%d]: state %x start %x full %d free %d required %d stopped %x\n",
+                channum, ch->state, ch->ch_start_tx, ch->tx_full,
+                ch->txd_free, ch->txd_required, sd_queue_stopped (ch->user));
+    }
+    /***********************************************/
+    /** Determine total amount of data to be sent **/
+    /***********************************************/
+    m2 = mem_token;
+    txd_need_cnt = 0;
+    for (len = OS_mem_token_tlen (m2); len > 0;
+         m2 = (void *) OS_mem_token_next (m2))
+    {
+        if (!OS_mem_token_len (m2))
+            continue;
+        txd_need_cnt++;
+        len -= OS_mem_token_len (m2);
+    }
+
+    if (txd_need_cnt == 0)
+    {
+        if (log_level >= LOG_MONITOR2)
+            printk ("%s channel %d: no TX data in User buffer\n", ci->devname, channum);
+        OS_mem_token_free (mem_token);
+        return 0;                   /* no data to send */
+    }
+    /*************************************************/
+    /** Are there sufficient descriptors available? **/
+    /*************************************************/
+    if (txd_need_cnt > ch->txd_num) /* never enough descriptors for this
+                                     * large a buffer */
+    {
+        if (log_level >= LOG_DEBUG)
+        {
+            printk ("start_xmit: discarding buffer, insufficient descriptor cnt %d, need %d.\n",
+                    ch->txd_num, txd_need_cnt + 1);
+        }
+        ch->s.tx_dropped++;
+        OS_mem_token_free (mem_token);
+        return 0;
+    }
+#if 0
+    spin_lock_irqsave (&ch->ch_txlock, flags);
+#endif
+    /************************************************************/
+    /** flow control the line if not enough descriptors remain **/
+    /************************************************************/
+    if (txd_need_cnt > ch->txd_free)
+    {
+        if (log_level >= LOG_MONITOR2)
+        {
+            printk ("start_xmit[%d]: EBUSY - need more descriptors, have %d of %d need %d\n",
+                    channum, ch->txd_free, ch->txd_num, txd_need_cnt);
+        }
+        ch->tx_full = 1;
+        ch->txd_required = txd_need_cnt;
+        sd_disable_xmit (ch->user);
+#if 0
+        spin_unlock_irqrestore (&ch->ch_txlock, flags);
+#endif
+        return EBUSY;               /* tell user to try again later */
+    }
+    /**************************************************/
+    /** Put the user data into MUSYCC data buffer(s) **/
+    /**************************************************/
+    m2 = mem_token;
+    md = ch->txd_usr_add;           /* get current available descriptor */
+
+    for (len = OS_mem_token_tlen (m2); len > 0; m2 = OS_mem_token_next (m2))
+    {
+        int         u = OS_mem_token_len (m2);
+
+        if (!u)
+            continue;
+        len -= u;
+
+        /*
+         * Enable following chunks, yet wait to enable the FIRST chunk until
+         * after ALL subsequent chunks are setup.
+         */
+        if (md != ch->txd_usr_add)  /* not first chunk */
+            u |= MUSYCC_TX_OWNED;   /* transfer ownership from HOST to MUSYCC */
+
+        if (len)                    /* not last chunk */
+            u |= EOBIRQ_ENABLE;
+        else if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
+        {
+            /*
+             * Per MUSYCC Ref 6.4.9 for Transparent Mode, the host must
+             * always clear EOMIRQ_ENABLE in every Transmit Buffer Descriptor
+             * (IE. don't set herein).
+             */
+            u |= EOBIRQ_ENABLE;
+        } else
+            u |= EOMIRQ_ENABLE;     /* EOM, last HDLC chunk */
+
+
+        /* last chunk in hdlc mode */
+        u |= (ch->p.idlecode << IDLE_CODE);
+        if (ch->p.pad_fill_count)
+        {
+#if 0
+            /* NOOP NOTE: u_int8_t cannot be > 0xFF */
+            /* sanitize pad_fill_count for maximums allowed by hardware */
+            if (ch->p.pad_fill_count > EXTRA_FLAGS_MASK)
+                ch->p.pad_fill_count = EXTRA_FLAGS_MASK;
+#endif
+            u |= (PADFILL_ENABLE | (ch->p.pad_fill_count << EXTRA_FLAGS));
+        }
+        md->mem_token = len ? 0 : mem_token;    /* Fill in mds on last
+                                                 * segment, others set ZERO
+                                                 * so that entire token is
+                                                 * removed ONLY when ALL
+                                                 * segments have been
+                                                 * transmitted. */
+
+        md->data = cpu_to_le32 (OS_vtophys (OS_mem_token_data (m2)));
+        FLUSH_MEM_WRITE ();
+        md->status = cpu_to_le32 (u);
+        --ch->txd_free;
+        md = md->snext;
+    }
+    FLUSH_MEM_WRITE ();
+
+
+    /*
+     * Now transfer ownership of first chunk from HOST to MUSYCC in order to
+     * fire-off this XMIT.
+     */
+    ch->txd_usr_add->status |= __constant_cpu_to_le32 (MUSYCC_TX_OWNED);
+    FLUSH_MEM_WRITE ();
+    ch->txd_usr_add = md;
+
+    len = OS_mem_token_tlen (mem_token);
+    atomic_add (len, &ch->tx_pending);
+    atomic_add (len, &ci->tx_pending);
+    ch->s.tx_packets++;
+    ch->s.tx_bytes += len;
+#if 0
+    spin_unlock_irqrestore (&ch->ch_txlock, flags);   /* allow pending
+                                                       * interrupt to sneak
+                                                       * thru */
+#endif
+
+    /*
+     * If an ONR was seen, then channel requires poking to restart
+     * transmission.
+     */
+    if (ch->ch_start_tx)
+    {
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,41)
+        SD_SEM_TAKE (&ci->sem_wdbusy, "_wd_");  /* only 1 thru here, per
+                                                 * board */
+        if ((ch->ch_start_tx == CH_START_TX_ONR) && (ch->p.chan_mode == CFG_CH_PROTO_TRANS))
+        {
+            /* ONR restart transmission from background loop */
+            ci->wd_notify = WD_NOTIFY_ONR;      /* enabled global watchdog
+                                                 * scan-thru  */
+        } else
+        {
+            /* start first transmission from background loop */
+            ci->wd_notify = WD_NOTIFY_1TX;      /* enabled global watchdog
+                                                 * scan-thru  */
+        }
+        musycc_chan_restart (ch);
+        SD_SEM_GIVE (&ci->sem_wdbusy);
+#else
+        musycc_chan_restart (ch);
+#endif
+    }
+#ifdef SBE_WAN256T3_ENABLE
+    wan256t3_led (ci, LED_TX, LEDV_G);
+#endif
+    return 0;
+}
+
+
+#if 0
+int
+musycc_set_chan (ci_t * ci, int channum, struct sbecom_chan_param * p)
+{
+    mch_t      *ch;
+    int         rok = 0;
+    int         n = 0;
+
+    if (channum < 0 || channum >= (MUSYCC_NPORTS * MUSYCC_NCHANS))      /* sanity chk param */
+        return ECHRNG;
+    if (!(ch = sd_find_chan (ci, channum)))
+        return ENOENT;
+    if (ch->channum != p->channum)
+        return EINVAL;
+    if (sd_line_is_ok (ch->user))
+    {
+        rok = 1;
+        sd_line_is_down (ch->user);
+    }
+    if (ch->state == UP &&          /* bring down in current configuration */
+        (ch->p.status != p->status ||
+         ch->p.chan_mode != p->chan_mode ||
+         ch->p.intr_mask != p->intr_mask ||
+         ch->txd_free < ch->txd_num))
+    {
+        if ((n = musycc_chan_down (ci, channum)))
+            return n;
+        if (ch->p.mode_56k != p->mode_56k)
+        {
+            ch->p = *p;             /* copy in new parameters */
+            musycc_update_timeslots (&ci->port[ch->channum / MUSYCC_NCHANS]);
+        } else
+            ch->p = *p;             /* copy in new parameters */
+        if ((n = musycc_chan_up (ci, channum)))
+            return n;
+        sd_enable_xmit (ch->user);  /* re-enable to catch flow controlled
+                                     * channel */
+    } else
+    {
+        if (ch->p.mode_56k != p->mode_56k)
+        {
+            ch->p = *p;             /* copy in new parameters */
+            musycc_update_timeslots (&ci->port[ch->channum / MUSYCC_NCHANS]);
+        } else
+            ch->p = *p;             /* copy in new parameters */
+    }
+
+    if (rok)
+        sd_line_is_up (ch->user);
+    return 0;
+}
+#endif
+
+
+int
+musycc_get_chan (ci_t * ci, int channum, struct sbecom_chan_param * p)
+{
+    mch_t      *ch;
+
+#if 0
+    if (channum < 0 || channum >= (MUSYCC_NPORTS * MUSYCC_NCHANS))      /* sanity chk param */
+        return ECHRNG;
+#endif
+    if (!(ch = sd_find_chan (ci, channum)))
+        return ENOENT;
+    *p = ch->p;
+    return 0;
+}
+
+
+int
+musycc_get_chan_stats (ci_t * ci, int channum, struct sbecom_chan_stats * p)
+{
+    mch_t      *ch;
+
+    if (channum < 0 || channum >= (MUSYCC_NPORTS * MUSYCC_NCHANS))      /* sanity chk param */
+        return ECHRNG;
+    if (!(ch = sd_find_chan (ci, channum)))
+        return ENOENT;
+    *p = ch->s;
+    p->tx_pending = atomic_read (&ch->tx_pending);
+    return 0;
+}
+
+
+
+#ifdef SBE_WAN256T3_ENABLE
+int
+musycc_chan_down (ci_t * ci, int channum)
+{
+    mch_t      *ch;
+    mpi_t      *pi;
+    int         i, gchan;
+
+    if (!(ch = sd_find_chan (ci, channum)))
+        return EINVAL;
+    pi = ch->up;
+    gchan = ch->gchan;
+
+    /* Deactivate the channel */
+    musycc_serv_req (pi, SR_CHANNEL_DEACTIVATE | SR_RX_DIRECTION | gchan);
+    ch->ch_start_rx = 0;
+    musycc_serv_req (pi, SR_CHANNEL_DEACTIVATE | SR_TX_DIRECTION | gchan);
+    ch->ch_start_tx = 0;
+
+    if (ch->state == DOWN)
+        return 0;
+    ch->state = DOWN;
+
+    pi->regram->thp[gchan] = 0;
+    pi->regram->tmp[gchan] = 0;
+    pi->regram->rhp[gchan] = 0;
+    pi->regram->rmp[gchan] = 0;
+    FLUSH_MEM_WRITE ();
+    for (i = 0; i < ch->txd_num; i++)
+    {
+        if (ch->mdt[i].mem_token != 0)
+            OS_mem_token_free (ch->mdt[i].mem_token);
+    }
+
+    for (i = 0; i < ch->rxd_num; i++)
+    {
+        if (ch->mdr[i].mem_token != 0)
+            OS_mem_token_free (ch->mdr[i].mem_token);
+    }
+
+    OS_kfree (ch->mdt);
+    ch->mdt = 0;
+    OS_kfree (ch->mdr);
+    ch->mdr = 0;
+
+    return 0;
+}
+#endif
+
+/*** End-of-File ***/
diff --git a/drivers/staging/cxt1e1/musycc.h b/drivers/staging/cxt1e1/musycc.h
new file mode 100644 (file)
index 0000000..d2c91ef
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ * $Id: musycc.h,v 1.3 2005/09/28 00:10:08 rickd PMCC4_3_1B $
+ */
+
+#ifndef _INC_MUSYCC_H_
+#define _INC_MUSYCC_H_
+
+/*-----------------------------------------------------------------------------
+ * musycc.h - Multichannel Synchronous Communications Controller
+ *            CN8778/8474A/8472A/8471A
+ *
+ * Copyright (C) 2002-2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@sbei.com
+ * SBE, Inc.  San Ramon, California  U.S.A.
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 1.3 $
+ * Last changed on $Date: 2005/09/28 00:10:08 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: musycc.h,v $
+ * Revision 1.3  2005/09/28 00:10:08  rickd
+ * Add GNU license info. Add PMCC4 PCI/DevIDs.  Implement new
+ * musycc reg&bits namings. Use PORTMAP_0 GCD grouping.
+ *
+ * Revision 1.2  2005/04/28 23:43:04  rickd
+ * Add RCS tracking heading.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#if defined (__FreeBSD__) || defined (__NetBSD__)
+#include <sys/types.h>
+#else
+#include <linux/types.h>
+#endif
+
+#define VINT8   volatile u_int8_t
+#define VINT32  volatile u_int32_t
+
+#ifdef __cplusplus
+extern      "C"
+{
+#endif
+
+#include "pmcc4_defs.h"
+
+
+/*------------------------------------------------------------------------
+//      Vendor, Board Identification definitions
+//------------------------------------------------------------------------
+*/
+
+#define PCI_VENDOR_ID_CONEXANT   0x14f1
+#define PCI_DEVICE_ID_CN8471     0x8471
+#define PCI_DEVICE_ID_CN8472     0x8472
+#define PCI_DEVICE_ID_CN8474     0x8474
+#define PCI_DEVICE_ID_CN8478     0x8478
+#define PCI_DEVICE_ID_CN8500     0x8500
+#define PCI_DEVICE_ID_CN8501     0x8501
+#define PCI_DEVICE_ID_CN8502     0x8502
+#define PCI_DEVICE_ID_CN8503     0x8503
+
+#define INT_QUEUE_SIZE    MUSYCC_NIQD
+
+/* RAM image of MUSYCC registers layed out as a C structure */
+    struct musycc_groupr
+    {
+        VINT32      thp[32];    /* Transmit Head Pointer [5-29]           */
+        VINT32      tmp[32];    /* Transmit Message Pointer [5-30]        */
+        VINT32      rhp[32];    /* Receive Head Pointer [5-29]            */
+        VINT32      rmp[32];    /* Receive Message Pointer [5-30]         */
+        VINT8       ttsm[128];  /* Time Slot Map [5-22]                   */
+        VINT8       tscm[256];  /* Subchannel Map [5-24]                  */
+        VINT32      tcct[32];   /* Channel Configuration [5-26]           */
+        VINT8       rtsm[128];  /* Time Slot Map [5-22]                   */
+        VINT8       rscm[256];  /* Subchannel Map [5-24]                  */
+        VINT32      rcct[32];   /* Channel Configuration [5-26]           */
+        VINT32      __glcd;     /* Global Configuration Descriptor [5-10] */
+        VINT32      __iqp;      /* Interrupt Queue Pointer [5-36]         */
+        VINT32      __iql;      /* Interrupt Queue Length [5-36]          */
+        VINT32      grcd;       /* Group Configuration Descriptor [5-16]  */
+        VINT32      mpd;        /* Memory Protection Descriptor [5-18]    */
+        VINT32      mld;        /* Message Length Descriptor [5-20]       */
+        VINT32      pcd;        /* Port Configuration Descriptor [5-19]   */
+    };
+
+/* hardware MUSYCC registers layed out as a C structure */
+    struct musycc_globalr
+    {
+        VINT32      gbp;        /* Group Base Pointer                     */
+        VINT32      dacbp;      /* Dual Address Cycle Base Pointer        */
+        VINT32      srd;        /* Service Request Descriptor             */
+        VINT32      isd;        /* Interrupt Service Descriptor           */
+        /*
+         * adjust __thp due to above 4 registers, which are not contained
+         * within musycc_groupr[]. All __XXX[] are just place holders,
+         * anyhow.
+         */
+        VINT32      __thp[32 - 4];      /* Transmit Head Pointer [5-29]           */
+        VINT32      __tmp[32];  /* Transmit Message Pointer [5-30]        */
+        VINT32      __rhp[32];  /* Receive Head Pointer [5-29]            */
+        VINT32      __rmp[32];  /* Receive Message Pointer [5-30]         */
+        VINT8       ttsm[128];  /* Time Slot Map [5-22]                   */
+        VINT8       tscm[256];  /* Subchannel Map [5-24]                  */
+        VINT32      tcct[32];   /* Channel Configuration [5-26]           */
+        VINT8       rtsm[128];  /* Time Slot Map [5-22]                   */
+        VINT8       rscm[256];  /* Subchannel Map [5-24]                  */
+        VINT32      rcct[32];   /* Channel Configuration [5-26]           */
+        VINT32      glcd;       /* Global Configuration Descriptor [5-10] */
+        VINT32      iqp;        /* Interrupt Queue Pointer [5-36]         */
+        VINT32      iql;        /* Interrupt Queue Length [5-36]          */
+        VINT32      grcd;       /* Group Configuration Descriptor [5-16]  */
+        VINT32      mpd;        /* Memory Protection Descriptor [5-18]    */
+        VINT32      mld;        /* Message Length Descriptor [5-20]       */
+        VINT32      pcd;        /* Port Configuration Descriptor [5-19]   */
+        VINT32      rbist;      /* Receive BIST status [5-4]              */
+        VINT32      tbist;      /* Receive BIST status [5-4]              */
+    };
+
+/* Global Config Descriptor bit macros */
+#define MUSYCC_GCD_ECLK_ENABLE  0x00000800      /* EBUS clock enable */
+#define MUSYCC_GCD_INTEL_SELECT 0x00000400      /* MPU type select */
+#define MUSYCC_GCD_INTA_DISABLE 0x00000008      /* PCI INTA disable */
+#define MUSYCC_GCD_INTB_DISABLE 0x00000004      /* PCI INTB disable */
+#define MUSYCC_GCD_BLAPSE       12      /* Position index for BLAPSE bit
+                                         * field */
+#define MUSYCC_GCD_ALAPSE       8       /* Position index for ALAPSE bit
+                                         * field */
+#define MUSYCC_GCD_ELAPSE       4       /* Position index for ELAPSE bit
+                                         * field */
+#define MUSYCC_GCD_PORTMAP_3    3       /* Reserved */
+#define MUSYCC_GCD_PORTMAP_2    2       /* Port 0=>Grp 0,1,2,3; Port 1=>Grp
+                                         * 4,5,6,7 */
+#define MUSYCC_GCD_PORTMAP_1    1       /* Port 0=>Grp 0,1; Port 1=>Grp 2,3,
+                                         * etc... */
+#define MUSYCC_GCD_PORTMAP_0    0       /* Port 0=>Grp 0; Port 1=>Grp 2,
+                                         * etc... */
+
+/* and board specific assignments... */
+#ifdef SBE_WAN256T3_ENABLE
+#define BLAPSE_VAL      0
+#define ALAPSE_VAL      0
+#define ELAPSE_VAL      7
+#define PORTMAP_VAL     MUSYCC_GCD_PORTMAP_2
+#endif
+
+#ifdef SBE_PMCC4_ENABLE
+#define BLAPSE_VAL      7
+#define ALAPSE_VAL      3
+#define ELAPSE_VAL      7
+#define PORTMAP_VAL     MUSYCC_GCD_PORTMAP_0
+#endif
+
+#define GCD_MAGIC   (((BLAPSE_VAL)<<(MUSYCC_GCD_BLAPSE)) | \
+                     ((ALAPSE_VAL)<<(MUSYCC_GCD_ALAPSE)) | \
+                     ((ELAPSE_VAL)<<(MUSYCC_GCD_ELAPSE)) | \
+                     (MUSYCC_GCD_ECLK_ENABLE) | PORTMAP_VAL)
+
+/* Group Config Descriptor bit macros */
+#define MUSYCC_GRCD_RX_ENABLE       0x00000001  /* Enable receive processing */
+#define MUSYCC_GRCD_TX_ENABLE       0x00000002  /* Enable transmit processing */
+#define MUSYCC_GRCD_SUBCHAN_DISABLE 0x00000004  /* Master disable for
+                                                 * subchanneling */
+#define MUSYCC_GRCD_OOFMP_DISABLE   0x00000008  /* Out of Frame message
+                                                 * processing disabled all
+                                                 * channels */
+#define MUSYCC_GRCD_OOFIRQ_DISABLE  0x00000010  /* Out of Frame/In Frame irqs
+                                                 * disabled */
+#define MUSYCC_GRCD_COFAIRQ_DISABLE 0x00000020  /* Change of Frame Alignment
+                                                 * irq disabled */
+#define MUSYCC_GRCD_INHRBSD         0x00000100  /* Receive Buffer Status
+                                                 * overwrite disabled */
+#define MUSYCC_GRCD_INHTBSD         0x00000200  /* Transmit Buffer Status
+                                                 * overwrite disabled */
+#define MUSYCC_GRCD_SF_ALIGN        0x00008000  /* External frame sync */
+#define MUSYCC_GRCD_MC_ENABLE       0x00000040  /* Message configuration bits
+                                                 * copy enable. Conexant sez
+                                                 * turn this on */
+#define MUSYCC_GRCD_POLLTH_16       0x00000001  /* Poll every 16th frame */
+#define MUSYCC_GRCD_POLLTH_32       0x00000002  /* Poll every 32nd frame */
+#define MUSYCC_GRCD_POLLTH_64       0x00000003  /* Poll every 64th frame */
+#define MUSYCC_GRCD_POLLTH_SHIFT    10  /* Position index for poll throttle
+                                         * bit field */
+#define MUSYCC_GRCD_SUERM_THRESH_SHIFT 16       /* Position index for SUERM
+                                                 * count threshold */
+
+/* Port Config Descriptor bit macros */
+#define MUSYCC_PCD_E1X2_MODE       2    /* Port mode in bits 0-2. T1 and E1 */
+#define MUSYCC_PCD_E1X4_MODE       3    /* are defined in cn847x.h */
+#define MUSYCC_PCD_NX64_MODE       4
+#define MUSYCC_PCD_TXDATA_RISING   0x00000010   /* Sample Tx data on TCLK
+                                                 * rising edge */
+#define MUSYCC_PCD_TXSYNC_RISING   0x00000020   /* Sample Tx frame sync on
+                                                 * TCLK rising edge */
+#define MUSYCC_PCD_RXDATA_RISING   0x00000040   /* Sample Rx data on RCLK
+                                                 * rising edge */
+#define MUSYCC_PCD_RXSYNC_RISING   0x00000080   /* Sample Rx frame sync on
+                                                 * RCLK rising edge */
+#define MUSYCC_PCD_ROOF_RISING     0x00000100   /* Sample Rx Out Of Frame
+                                                 * signal on RCLK rising edge */
+#define MUSYCC_PCD_TX_DRIVEN       0x00000200   /* No mapped timeslots causes
+                                                 * logic 1 on output, else
+                                                 * tristate */
+#define MUSYCC_PCD_PORTMODE_MASK   0xfffffff8   /* For changing the port mode
+                                                 * between E1 and T1 */
+
+/* Time Slot Descriptor bit macros */
+#define MUSYCC_TSD_MODE_64KBPS              4
+#define MUSYCC_TSD_MODE_56KBPS              5
+#define MUSYCC_TSD_SUBCHANNEL_WO_FIRST      6
+#define MUSYCC_TSD_SUBCHANNEL_WITH_FIRST    7
+
+/* Message Descriptor bit macros */
+#define MUSYCC_MDT_BASE03_ADDR     0x00006000
+
+/* Channel Config Descriptor bit macros */
+#define MUSYCC_CCD_BUFIRQ_DISABLE  0x00000002   /* BUFF and ONR irqs disabled */
+#define MUSYCC_CCD_EOMIRQ_DISABLE  0x00000004   /* EOM irq disabled */
+#define MUSYCC_CCD_MSGIRQ_DISABLE  0x00000008   /* LNG, FCS, ALIGN, and ABT
+                                                 * irqs disabled */
+#define MUSYCC_CCD_IDLEIRQ_DISABLE 0x00000010   /* CHABT, CHIC, and SHT irqs
+                                                 * disabled */
+#define MUSYCC_CCD_FILTIRQ_DISABLE 0x00000020   /* SFILT irq disabled */
+#define MUSYCC_CCD_SDECIRQ_DISABLE 0x00000040   /* SDEC irq disabled */
+#define MUSYCC_CCD_SINCIRQ_DISABLE 0x00000080   /* SINC irq disabled */
+#define MUSYCC_CCD_SUERIRQ_DISABLE 0x00000100   /* SUERR irq disabled */
+#define MUSYCC_CCD_FCS_XFER        0x00000200   /* Propagate FCS along with
+                                                 * received data */
+#define MUSYCC_CCD_PROTO_SHIFT     12   /* Position index for protocol bit
+                                         * field */
+#define MUSYCC_CCD_TRANS           0    /* Protocol mode in bits 12-14 */
+#define MUSYCC_CCD_SS7             1
+#define MUSYCC_CCD_HDLC_FCS16      2
+#define MUSYCC_CCD_HDLC_FCS32      3
+#define MUSYCC_CCD_EOPIRQ_DISABLE  0x00008000   /* EOP irq disabled */
+#define MUSYCC_CCD_INVERT_DATA     0x00800000   /* Invert data */
+#define MUSYCC_CCD_MAX_LENGTH      10   /* Position index for max length bit
+                                         * field */
+#define MUSYCC_CCD_BUFFER_LENGTH   16   /* Position index for internal data
+                                         * buffer length */
+#define MUSYCC_CCD_BUFFER_LOC      24   /* Position index for internal data
+                                         * buffer starting location */
+
+/****************************************************************************
+ * Interrupt Descriptor Information */
+
+#define INT_EMPTY_ENTRY     0xfeedface
+#define INT_EMPTY_ENTRY2    0xdeadface
+
+/****************************************************************************
+ * Interrupt Status Descriptor
+ *
+ * NOTE: One must first fetch the value of the interrupt status descriptor
+ * into a local variable, then pass that value into the read macros. This
+ * is required to avoid race conditions.
+ ***/
+
+#define INTRPTS_NEXTINT_M      0x7FFF0000
+#define INTRPTS_NEXTINT_S      16
+#define INTRPTS_NEXTINT(x)     ((x & INTRPTS_NEXTINT_M) >> INTRPTS_NEXTINT_S)
+
+#define INTRPTS_INTFULL_M      0x00008000
+#define INTRPTS_INTFULL_S      15
+#define INTRPTS_INTFULL(x)     ((x & INTRPTS_INTFULL_M) >> INTRPTS_INTFULL_S)
+
+#define INTRPTS_INTCNT_M       0x00007FFF
+#define INTRPTS_INTCNT_S       0
+#define INTRPTS_INTCNT(x)      ((x & INTRPTS_INTCNT_M) >> INTRPTS_INTCNT_S)
+
+
+/****************************************************************************
+ * Interrupt Descriptor
+ ***/
+
+#define INTRPT_DIR_M           0x80000000
+#define INTRPT_DIR_S           31
+#define INTRPT_DIR(x)          ((x & INTRPT_DIR_M) >> INTRPT_DIR_S)
+
+#define INTRPT_GRP_M           0x60000000
+#define INTRPT_GRP_MSB_M       0x00004000
+#define INTRPT_GRP_S           29
+#define INTRPT_GRP_MSB_S       12
+#define INTRPT_GRP(x)          (((x & INTRPT_GRP_M) >> INTRPT_GRP_S) | \
+                               ((x & INTRPT_GRP_MSB_M) >> INTRPT_GRP_MSB_S))
+
+#define INTRPT_CH_M            0x1F000000
+#define INTRPT_CH_S            24
+#define INTRPT_CH(x)           ((x & INTRPT_CH_M) >> INTRPT_CH_S)
+
+#define INTRPT_EVENT_M         0x00F00000
+#define INTRPT_EVENT_S         20
+#define INTRPT_EVENT(x)        ((x & INTRPT_EVENT_M) >> INTRPT_EVENT_S)
+
+#define INTRPT_ERROR_M         0x000F0000
+#define INTRPT_ERROR_S         16
+#define INTRPT_ERROR(x)        ((x & INTRPT_ERROR_M) >> INTRPT_ERROR_S)
+
+#define INTRPT_ILOST_M         0x00008000
+#define INTRPT_ILOST_S         15
+#define INTRPT_ILOST(x)        ((x & INTRPT_ILOST_M) >> INTRPT_ILOST_S)
+
+#define INTRPT_PERR_M          0x00004000
+#define INTRPT_PERR_S          14
+#define INTRPT_PERR(x)         ((x & INTRPT_PERR_M) >> INTRPT_PERR_S)
+
+#define INTRPT_BLEN_M          0x00003FFF
+#define INTRPT_BLEN_S          0
+#define INTRPT_BLEN(x)         ((x & INTRPT_BLEN_M) >> INTRPT_BLEN_S)
+
+
+/* Buffer Descriptor bit macros */
+#define OWNER_BIT       0x80000000      /* Set for MUSYCC owner on xmit, host
+                                         * owner on receive */
+#define HOST_TX_OWNED   0x00000000      /* Host owns descriptor */
+#define MUSYCC_TX_OWNED 0x80000000      /* MUSYCC owns descriptor */
+#define HOST_RX_OWNED   0x80000000      /* Host owns descriptor */
+#define MUSYCC_RX_OWNED 0x00000000      /* MUSYCC owns descriptor */
+
+#define POLL_DISABLED   0x40000000      /* MUSYCC not allowed to poll buffer
+                                         * for ownership */
+#define EOMIRQ_ENABLE   0x20000000      /* This buffer contains the end of
+                                         * the message */
+#define EOBIRQ_ENABLE   0x10000000      /* EOB irq enabled */
+#define PADFILL_ENABLE  0x01000000      /* Enable padfill */
+#define REPEAT_BIT      0x00008000      /* Bit on for FISU descriptor */
+#define LENGTH_MASK         0X3fff      /* This part of status descriptor is
+                                         * length */
+#define IDLE_CODE               25      /* Position index for idle code (2
+                                         * bits) */
+#define EXTRA_FLAGS             16      /* Position index for minimum flags
+                                         * between messages (8 bits) */
+#define IDLE_CODE_MASK        0x03      /* Gets rid of garbage before the
+                                         * pattern is OR'd in */
+#define EXTRA_FLAGS_MASK      0xff      /* Gets rid of garbage before the
+                                         * pattern is OR'd in */
+#define PCI_PERMUTED_OWNER_BIT  0x00000080      /* For flipping the bit on
+                                                 * the polled mode descriptor */
+
+/* Service Request Descriptor bit macros */
+#define SREQ  8                 /* Position index for service request bit
+                                 * field */
+#define SR_NOOP                 (0<<(SREQ))     /* No Operation. Generates SACK */
+#define SR_CHIP_RESET           (1<<(SREQ))     /* Soft chip reset */
+#define SR_GROUP_RESET          (2<<(SREQ))     /* Group reset */
+#define SR_GLOBAL_INIT          (4<<(SREQ))     /* Global init: read global
+                                                 * config deswc and interrupt
+                                                 * queue desc */
+#define SR_GROUP_INIT           (5<<(SREQ))     /* Group init: read Timeslot
+                                                 * and Subchannel maps,
+                                                 * Channel Config, */
+    /*
+     * Group Config, Memory Protect, Message Length, and Port Config
+     * Descriptors
+     */
+#define SR_CHANNEL_ACTIVATE     (8<<(SREQ))     /* Init channel, read Head
+                                                 * Pointer, process first
+                                                 * Message Descriptor */
+#define SR_GCHANNEL_MASK        0x001F          /* channel portion (gchan) */
+#define SR_CHANNEL_DEACTIVATE   (9<<(SREQ))     /* Stop channel processing */
+#define SR_JUMP                 (10<<(SREQ))    /* a: Process new Message
+                                                 * List */
+#define SR_CHANNEL_CONFIG       (11<<(SREQ))    /* b: Read channel
+                                                 * Configuration Descriptor */
+#define SR_GLOBAL_CONFIG        (16<<(SREQ))    /* 10: Read Global
+                                                 * Configuration Descriptor */
+#define SR_INTERRUPT_Q          (17<<(SREQ))    /* 11: Read Interrupt Queue
+                                                 * Descriptor */
+#define SR_GROUP_CONFIG         (18<<(SREQ))    /* 12: Read Group
+                                                 * Configuration Descriptor */
+#define SR_MEMORY_PROTECT       (19<<(SREQ))    /* 13: Read Memory Protection
+                                                 * Descriptor */
+#define SR_MESSAGE_LENGTH       (20<<(SREQ))    /* 14: Read Message Length
+                                                 * Descriptor */
+#define SR_PORT_CONFIG          (21<<(SREQ))    /* 15: Read Port
+                                                 * Configuration Descriptor */
+#define SR_TIMESLOT_MAP         (24<<(SREQ))    /* 18: Read Timeslot Map */
+#define SR_SUBCHANNEL_MAP       (25<<(SREQ))    /* 19: Read Subchannel Map */
+#define SR_CHAN_CONFIG_TABLE    (26<<(SREQ))    /* 20: Read Channel
+                                                 * Configuration Table for
+                                                 * the group */
+#define SR_TX_DIRECTION         0x00000020      /* Transmit direction bit.
+                                                 * Bit off indicates receive
+                                                 * direction */
+#define SR_RX_DIRECTION         0x00000000
+
+/* Interrupt Descriptor bit macros */
+#define GROUP10                     29  /* Position index for the 2 LS group
+                                         * bits */
+#define CHANNEL                     24  /* Position index for channel bits */
+#define INT_IQD_TX          0x80000000
+#define INT_IQD_GRP         0x60000000
+#define INT_IQD_CHAN        0x1f000000
+#define INT_IQD_EVENT       0x00f00000
+#define INT_IQD_ERROR       0x000f0000
+#define INT_IQD_ILOST       0x00008000
+#define INT_IQD_PERR        0x00004000
+#define INT_IQD_BLEN        0x00003fff
+
+/* Interrupt Descriptor Events */
+#define EVE_EVENT               20      /* Position index for event bits */
+#define EVE_NONE                0       /* No event to report in this
+                                         * interrupt */
+#define EVE_SACK                1       /* Service Request acknowledge */
+#define EVE_EOB                 2       /* End of Buffer */
+#define EVE_EOM                 3       /* End of Message */
+#define EVE_EOP                 4       /* End of Padfill */
+#define EVE_CHABT               5       /* Change to Abort Code */
+#define EVE_CHIC                6       /* Change to Idle Code */
+#define EVE_FREC                7       /* Frame Recovery */
+#define EVE_SINC                8       /* MTP2 SUERM Increment */
+#define EVE_SDEC                9       /* MTP2 SUERM Decrement */
+#define EVE_SFILT               10      /* MTP2 SUERM Filtered Message */
+/* Interrupt Descriptor Errors */
+#define ERR_ERRORS              16      /* Position index for error bits */
+#define ERR_BUF                 1       /* Buffer Error */
+#define ERR_COFA                2       /* Change of Frame Alignment Error */
+#define ERR_ONR                 3       /* Owner Bit Error */
+#define ERR_PROT                4       /* Memory Protection Error */
+#define ERR_OOF                 8       /* Out of Frame Error */
+#define ERR_FCS                 9       /* FCS Error */
+#define ERR_ALIGN               10      /* Octet Alignment Error */
+#define ERR_ABT                 11      /* Abort Termination */
+#define ERR_LNG                 12      /* Long Message Error */
+#define ERR_SHT                 13      /* Short Message Error */
+#define ERR_SUERR               14      /* SUERM threshold exceeded */
+#define ERR_PERR                15      /* PCI Parity Error */
+/* Other Stuff */
+#define TRANSMIT_DIRECTION  0x80000000  /* Transmit direction bit. Bit off
+                                         * indicates receive direction */
+#define ILOST               0x00008000  /* Interrupt Lost */
+#define GROUPMSB            0x00004000  /* Group number MSB */
+#define SACK_IMAGE          0x00100000  /* Used in IRQ for semaphore test */
+#define INITIAL_STATUS      0x10000     /* IRQ status should be this after
+                                         * reset */
+
+/*  This must be defined on an entire channel group (Port) basis */
+#define SUERM_THRESHOLD     0x1f
+
+#ifdef __cplusplus
+}
+#endif
+
+#undef VINT32
+#undef VINT8
+
+#endif                          /*** _INC_MUSYCC_H_ ***/
+
+/*** End-of-File ***/
diff --git a/drivers/staging/cxt1e1/ossiRelease.c b/drivers/staging/cxt1e1/ossiRelease.c
new file mode 100644 (file)
index 0000000..a560298
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * $Id: ossiRelease.c,v 1.2 2008/05/08 20:14:03 rdobbs PMCC4_3_1B $
+ */
+
+/*-----------------------------------------------------------------------------
+ * ossiRelease.c -
+ *
+ * This string will be embedded into the executable and will track the
+ * release.  The embedded string may be displayed using the following:
+ *
+ *      strings <filename> | grep \$Rel
+ *
+ * Copyright (C) 2002-2008  One Stop Systems, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@onestopsystems.com
+ * One Stop Systems, Inc.  Escondido, California  U.S.A.
+ *
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 1.2 $
+ * Last changed on $Date: 2008/05/08 20:14:03 $
+ * Changed by $Author: rdobbs $
+ *-----------------------------------------------------------------------------
+ */
+
+
+char pmcc4_OSSI_release[] = "$Release: PMCC4_3_1B,  Copyright (c) 2008 One Stop Systems$";
+
+/***  End-of-File  ***/
diff --git a/drivers/staging/cxt1e1/pmc93x6_eeprom.c b/drivers/staging/cxt1e1/pmc93x6_eeprom.c
new file mode 100644 (file)
index 0000000..02c829b
--- /dev/null
@@ -0,0 +1,559 @@
+/* pmc93x6_eeprom.c - PMC's 93LC46 EEPROM Device
+ *
+ *    The 93LC46 is a low-power, serial Electrically Erasable and
+ *    Programmable Read Only Memory organized as 128 8-bit bytes.
+ *
+ *    Accesses to the 93LC46 are done in a bit serial stream, organized
+ *    in a 3 wire format.  Writes are internally timed by the device
+ *    (the In data bit is pulled low until the write is complete and
+ *    then is pulled high) and take about 6 milliseconds.
+ *
+ * Copyright (C) 2003-2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include <linux/types.h>
+#include "pmcc4_sysdep.h"
+#include "sbecom_inline_linux.h"
+#include "pmcc4.h"
+#include "sbe_promformat.h"
+
+#ifndef TRUE
+#define TRUE   1
+#define FALSE  0
+#endif
+
+#ifdef SBE_INCLUDE_SYMBOLS
+#define STATIC
+#else
+#define STATIC  static
+#endif
+
+
+/*------------------------------------------------------------------------
+ *      EEPROM address definitions
+ *------------------------------------------------------------------------
+ *
+ *      The offset in the definitions below allows the test to skip over
+ *      areas of the EEPROM that other programs (such a VxWorks) are
+ *      using.
+ */
+
+#define EE_MFG      (long)0     /* Index to manufacturing record */
+#define EE_FIRST    0x28        /* Index to start testing at */
+#define EE_LIMIT    128         /* Index to end testing at */
+
+
+/*  Bit Ordering for Instructions
+**
+**  A0, A1, A2, A3, A4, A5, A6, OP0, OP1, SB   (lsb, or 1st bit out)
+**
+*/
+
+#define EPROM_EWEN      0x0019  /* Erase/Write enable (reversed) */
+#define EPROM_EWDS      0x0001  /* Erase/Write disable (reversed) */
+#define EPROM_READ      0x0003  /* Read (reversed) */
+#define EPROM_WRITE     0x0005  /* Write (reversed) */
+#define EPROM_ERASE     0x0007  /* Erase (reversed) */
+#define EPROM_ERAL      0x0009  /* Erase All (reversed) */
+#define EPROM_WRAL      0x0011  /* Write All (reversed) */
+
+#define EPROM_ADR_SZ    7       /* Number of bits in offset address */
+#define EPROM_OP_SZ     3       /* Number of bits in command */
+#define SIZE_ADDR_OP    (EPROM_ADR_SZ + EPROM_OP_SZ)
+#define LC46A_MAX_OPS   10      /* Number of bits in Instruction */
+#define NUM_OF_BITS     8       /* Number of bits in data */
+
+
+/* EEPROM signal bits */
+#define EPROM_ACTIVE_OUT_BIT    0x0001  /* Out data bit */
+#define EPROM_ACTIVE_IN_BIT     0x0002  /* In data bit */
+#define ACTIVE_IN_BIT_SHIFT     0x0001  /* Shift In data bit to LSB */
+#define EPROM_ENCS              0x0004  /* Set EEPROM CS during operation */
+
+
+/*------------------------------------------------------------------------
+ *      The ByteReverse table is used to reverses the 8 bits within a byte
+ *------------------------------------------------------------------------
+ */
+
+static unsigned char ByteReverse[256];
+static int  ByteReverseBuilt = FALSE;
+
+
+/*------------------------------------------------------------------------
+ *      mfg_template - initial serial EEPROM data structure
+ *------------------------------------------------------------------------
+ */
+
+short       mfg_template[sizeof (FLD_TYPE2)] =
+{
+    PROM_FORMAT_TYPE2,          /* type; */
+    0x00, 0x1A,                 /* length[2]; */
+    0x00, 0x00, 0x00, 0x00,     /* Crc32[4]; */
+    0x11, 0x76,                 /* Id[2]; */
+    0x07, 0x05,                 /* SubId[2] E1; */
+    0x00, 0xA0, 0xD6, 0x00, 0x00, 0x00, /* Serial[6]; */
+    0x00, 0x00, 0x00, 0x00,     /* CreateTime[4]; */
+    0x00, 0x00, 0x00, 0x00,     /* HeatRunTime[4]; */
+    0x00, 0x00, 0x00, 0x00,     /* HeatRunIterations[4]; */
+    0x00, 0x00, 0x00, 0x00,     /* HeatRunErrors[4]; */
+};
+
+
+/*------------------------------------------------------------------------
+ *      BuildByteReverse - build the 8-bit reverse table
+ *------------------------------------------------------------------------
+ *
+ *      The 'ByteReverse' table reverses the 8 bits within a byte
+ *      (the MSB becomes the LSB etc.).
+ */
+
+STATIC void
+BuildByteReverse (void)
+{
+    long        half;           /* Used to build by powers to 2 */
+    int         i;
+
+    ByteReverse[0] = 0;
+
+    for (half = 1; half < sizeof (ByteReverse); half <<= 1)
+        for (i = 0; i < half; i++)
+            ByteReverse[half + i] = (char) (ByteReverse[i] | (0x80 / half));
+
+    ByteReverseBuilt = TRUE;
+}
+
+
+/*------------------------------------------------------------------------
+ *      eeprom_delay - small delay for EEPROM timing
+ *------------------------------------------------------------------------
+ */
+
+STATIC void
+eeprom_delay (void)
+{
+    int         timeout;
+
+    for (timeout = 20; timeout; --timeout)
+    {
+        OS_uwait_dummy ();
+    }
+}
+
+
+/*------------------------------------------------------------------------
+ *      eeprom_put_byte - Send a byte to the EEPROM serially
+ *------------------------------------------------------------------------
+ *
+ *      Given the PCI address and the data, this routine serially sends
+ *      the data to the EEPROM.
+ */
+
+void
+eeprom_put_byte (long addr, long data, int count)
+{
+    u_int32_t output;
+
+    while (--count >= 0)
+    {
+        output = (data & EPROM_ACTIVE_OUT_BIT) ? 1 : 0; /* Get next data bit */
+        output |= EPROM_ENCS;       /* Add Chip Select */
+        data >>= 1;
+
+        eeprom_delay ();
+        pci_write_32 ((u_int32_t *) addr, output);      /* Output it */
+    }
+}
+
+
+/*------------------------------------------------------------------------
+ *      eeprom_get_byte - Receive a byte from the EEPROM serially
+ *------------------------------------------------------------------------
+ *
+ *      Given the PCI address, this routine serially fetches the data
+ *      from the  EEPROM.
+ */
+
+u_int32_t
+eeprom_get_byte (long addr)
+{
+    u_int32_t   input;
+    u_int32_t   data;
+    int         count;
+
+/*  Start the Reading of DATA
+**
+**  The first read is a dummy as the data is latched in the
+**  EPLD and read on the next read access to the EEPROM.
+*/
+
+    input = pci_read_32 ((u_int32_t *) addr);
+
+    data = 0;
+    count = NUM_OF_BITS;
+    while (--count >= 0)
+    {
+        eeprom_delay ();
+        input = pci_read_32 ((u_int32_t *) addr);
+
+        data <<= 1;                 /* Shift data over */
+        data |= (input & EPROM_ACTIVE_IN_BIT) ? 1 : 0;
+
+    }
+
+    return data;
+}
+
+
+/*------------------------------------------------------------------------
+ *      disable_pmc_eeprom - Disable writes to the EEPROM
+ *------------------------------------------------------------------------
+ *
+ *      Issue the EEPROM command to disable writes.
+ */
+
+STATIC void
+disable_pmc_eeprom (long addr)
+{
+    eeprom_put_byte (addr, EPROM_EWDS, SIZE_ADDR_OP);
+
+    pci_write_32 ((u_int32_t *) addr, 0);       /* this removes Chip Select
+                                                 * from EEPROM */
+}
+
+
+/*------------------------------------------------------------------------
+ *      enable_pmc_eeprom - Enable writes to the EEPROM
+ *------------------------------------------------------------------------
+ *
+ *      Issue the EEPROM command to enable writes.
+ */
+
+STATIC void
+enable_pmc_eeprom (long addr)
+{
+    eeprom_put_byte (addr, EPROM_EWEN, SIZE_ADDR_OP);
+
+    pci_write_32 ((u_int32_t *) addr, 0);       /* this removes Chip Select
+                                                 * from EEPROM */
+}
+
+
+/*------------------------------------------------------------------------
+ *      pmc_eeprom_read - EEPROM location read
+ *------------------------------------------------------------------------
+ *
+ *      Given a EEPROM PCI address and location offset, this routine returns
+ *      the contents of the specified location to the calling routine.
+ */
+
+u_int32_t
+pmc_eeprom_read (long addr, long mem_offset)
+{
+    u_int32_t   data;           /* Data from chip */
+
+    if (!ByteReverseBuilt)
+        BuildByteReverse ();
+
+    mem_offset = ByteReverse[0x7F & mem_offset];        /* Reverse address */
+    /*
+     * NOTE: The max offset address is 128 or half the reversal table. So the
+     * LSB is always zero and counts as a built in shift of one bit.  So even
+     * though we need to shift 3 bits to make room for the command, we only
+     * need to shift twice more because of the built in shift.
+     */
+    mem_offset <<= 2;               /* Shift for command */
+    mem_offset |= EPROM_READ;       /* Add command */
+
+    eeprom_put_byte (addr, mem_offset, SIZE_ADDR_OP);   /* Output chip address */
+
+    data = eeprom_get_byte (addr);  /* Read chip data */
+
+    pci_write_32 ((u_int32_t *) addr, 0);       /* Remove Chip Select from
+                                                 * EEPROM */
+
+    return (data & 0x000000FF);
+}
+
+
+/*------------------------------------------------------------------------
+ *      pmc_eeprom_write - EEPROM location write
+ *------------------------------------------------------------------------
+ *
+ *      Given a EEPROM PCI address, location offset and value, this
+ *      routine writes the value to the specified location.
+ *
+ *      Note: it is up to the caller to determine if the write
+ *      operation succeeded.
+ */
+
+int
+pmc_eeprom_write (long addr, long mem_offset, u_int32_t data)
+{
+    volatile u_int32_t temp;
+    int         count;
+
+    if (!ByteReverseBuilt)
+        BuildByteReverse ();
+
+    mem_offset = ByteReverse[0x7F & mem_offset];        /* Reverse address */
+    /*
+     * NOTE: The max offset address is 128 or half the reversal table. So the
+     * LSB is always zero and counts as a built in shift of one bit.  So even
+     * though we need to shift 3 bits to make room for the command, we only
+     * need to shift twice more because of the built in shift.
+     */
+    mem_offset <<= 2;               /* Shift for command */
+    mem_offset |= EPROM_WRITE;      /* Add command */
+
+    eeprom_put_byte (addr, mem_offset, SIZE_ADDR_OP);   /* Output chip address */
+
+    data = ByteReverse[0xFF & data];/* Reverse data */
+    eeprom_put_byte (addr, data, NUM_OF_BITS);  /* Output chip data */
+
+    pci_write_32 ((u_int32_t *) addr, 0);       /* Remove Chip Select from
+                                                 * EEPROM */
+
+/*
+**  Must see Data In at a low state before completing this transaction.
+**
+**  Afterwards, the data bit will return to a high state, ~6 ms, terminating
+**  the operation.
+*/
+    pci_write_32 ((u_int32_t *) addr, EPROM_ENCS);      /* Re-enable Chip Select */
+    temp = pci_read_32 ((u_int32_t *) addr);    /* discard first read */
+    temp = pci_read_32 ((u_int32_t *) addr);
+    if (temp & EPROM_ACTIVE_IN_BIT)
+    {
+        temp = pci_read_32 ((u_int32_t *) addr);
+        if (temp & EPROM_ACTIVE_IN_BIT)
+        {
+            pci_write_32 ((u_int32_t *) addr, 0);       /* Remove Chip Select
+                                                         * from EEPROM */
+            return (1);
+        }
+    }
+    count = 1000;
+    while (count--)
+    {
+        for (temp = 0; temp < 0x10; temp++)
+            OS_uwait_dummy ();
+
+        if (pci_read_32 ((u_int32_t *) addr) & EPROM_ACTIVE_IN_BIT)
+            break;
+    }
+
+    if (count == -1)
+        return (2);
+
+    return (0);
+}
+
+
+/*------------------------------------------------------------------------
+ *      pmcGetBuffValue - read the specified value from buffer
+ *------------------------------------------------------------------------
+ */
+
+long
+pmcGetBuffValue (char *ptr, int size)
+{
+    long        value = 0;
+    int         index;
+
+    for (index = 0; index < size; ++index)
+    {
+        value <<= 8;
+        value |= ptr[index] & 0xFF;
+    }
+
+    return value;
+}
+
+
+/*------------------------------------------------------------------------
+ *      pmcSetBuffValue - save the specified value to buffer
+ *------------------------------------------------------------------------
+ */
+
+void
+pmcSetBuffValue (char *ptr, long value, int size)
+{
+    int         index = size;
+
+    while (--index >= 0)
+    {
+        ptr[index] = (char) (value & 0xFF);
+        value >>= 8;
+    }
+}
+
+
+/*------------------------------------------------------------------------
+ *      pmc_eeprom_read_buffer - read EEPROM data into specified buffer
+ *------------------------------------------------------------------------
+ */
+
+void
+pmc_eeprom_read_buffer (long addr, long mem_offset, char *dest_ptr, int size)
+{
+    while (--size >= 0)
+        *dest_ptr++ = (char) pmc_eeprom_read (addr, mem_offset++);
+}
+
+
+/*------------------------------------------------------------------------
+ *      pmc_eeprom_write_buffer - write EEPROM data from specified buffer
+ *------------------------------------------------------------------------
+ */
+
+void
+pmc_eeprom_write_buffer (long addr, long mem_offset, char *dest_ptr, int size)
+{
+    enable_pmc_eeprom (addr);
+
+    while (--size >= 0)
+        pmc_eeprom_write (addr, mem_offset++, *dest_ptr++);
+
+    disable_pmc_eeprom (addr);
+}
+
+
+/*------------------------------------------------------------------------
+ *      pmcCalcCrc - calculate the CRC for the serial EEPROM structure
+ *------------------------------------------------------------------------
+ */
+
+u_int32_t
+pmcCalcCrc_T01 (void *bufp)
+{
+    FLD_TYPE2  *buf = bufp;
+    u_int32_t   crc;            /* CRC of the structure */
+
+    /* Calc CRC for type and length fields */
+    sbeCrc (
+            (u_int8_t *) &buf->type,
+            (u_int32_t) STRUCT_OFFSET (FLD_TYPE1, Crc32),
+            (u_int32_t) 0,
+            (u_int32_t *) &crc);
+
+#ifdef EEPROM_TYPE_DEBUG
+    printk ("sbeCrc: crc 1 calculated as %08x\n", crc); /* RLD DEBUG */
+#endif
+    return ~crc;
+}
+
+u_int32_t
+pmcCalcCrc_T02 (void *bufp)
+{
+    FLD_TYPE2  *buf = bufp;
+    u_int32_t   crc;            /* CRC of the structure */
+
+    /* Calc CRC for type and length fields */
+    sbeCrc (
+            (u_int8_t *) &buf->type,
+            (u_int32_t) STRUCT_OFFSET (FLD_TYPE2, Crc32),
+            (u_int32_t) 0,
+            (u_int32_t *) &crc);
+
+    /* Calc CRC for remaining fields */
+    sbeCrc (
+            (u_int8_t *) &buf->Id[0],
+            (u_int32_t) (sizeof (FLD_TYPE2) - STRUCT_OFFSET (FLD_TYPE2, Id)),
+            (u_int32_t) crc,
+            (u_int32_t *) &crc);
+
+#ifdef EEPROM_TYPE_DEBUG
+    printk ("sbeCrc: crc 2 calculated as %08x\n", crc); /* RLD DEBUG */
+#endif
+    return crc;
+}
+
+
+/*------------------------------------------------------------------------
+ *      pmc_init_seeprom - initialize the serial EEPROM structure
+ *------------------------------------------------------------------------
+ *
+ *      At the front of the serial EEPROM there is a record that contains
+ *      manufacturing information.  If the info does not already exist, it
+ *      is created.  The only field modifiable by the operator is the
+ *      serial number field.
+ */
+
+void
+pmc_init_seeprom (u_int32_t addr, u_int32_t serialNum)
+{
+    PROMFORMAT  buffer;         /* Memory image of structure */
+    u_int32_t   crc;            /* CRC of structure */
+    time_t      createTime;
+    int         i;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+    createTime = CURRENT_TIME;
+#else
+    createTime = get_seconds ();
+#endif
+
+    /* use template data */
+    for (i = 0; i < sizeof (FLD_TYPE2); ++i)
+        buffer.bytes[i] = mfg_template[i];
+
+    /* Update serial number field in buffer */
+    pmcSetBuffValue (&buffer.fldType2.Serial[3], serialNum, 3);
+
+    /* Update create time field in buffer */
+    pmcSetBuffValue (&buffer.fldType2.CreateTime[0], createTime, 4);
+
+    /* Update CRC field in buffer */
+    crc = pmcCalcCrc_T02 (&buffer);
+    pmcSetBuffValue (&buffer.fldType2.Crc32[0], crc, 4);
+
+#ifdef DEBUG
+    for (i = 0; i < sizeof (FLD_TYPE2); ++i)
+        printk ("[%02X] = %02X\n", i, buffer.bytes[i] & 0xFF);
+#endif
+
+    /* Write structure to serial EEPROM */
+    pmc_eeprom_write_buffer (addr, EE_MFG, (char *) &buffer, sizeof (FLD_TYPE2));
+}
+
+
+char
+pmc_verify_cksum (void *bufp)
+{
+    FLD_TYPE1  *buf1 = bufp;
+    FLD_TYPE2  *buf2 = bufp;
+    u_int32_t   crc1, crc2;     /* CRC read from EEPROM */
+
+    /* Retrieve contents of CRC field */
+    crc1 = pmcGetBuffValue (&buf1->Crc32[0], sizeof (buf1->Crc32));
+#ifdef EEPROM_TYPE_DEBUG
+    printk ("EEPROM: chksum 1 reads   as %08x\n", crc1);        /* RLD DEBUG */
+#endif
+    if ((buf1->type == PROM_FORMAT_TYPE1) &&
+        (pmcCalcCrc_T01 ((void *) buf1) == crc1))
+        return PROM_FORMAT_TYPE1;   /* checksum type 1 verified */
+
+    crc2 = pmcGetBuffValue (&buf2->Crc32[0], sizeof (buf2->Crc32));
+#ifdef EEPROM_TYPE_DEBUG
+    printk ("EEPROM: chksum 2 reads   as %08x\n", crc2);        /* RLD DEBUG */
+#endif
+    if ((buf2->type == PROM_FORMAT_TYPE2) &&
+        (pmcCalcCrc_T02 ((void *) buf2) == crc2))
+        return PROM_FORMAT_TYPE2;   /* checksum type 2 verified */
+
+    return PROM_FORMAT_Unk;         /* failed to validate */
+}
+
+
+/*** End-of-File ***/
diff --git a/drivers/staging/cxt1e1/pmc93x6_eeprom.h b/drivers/staging/cxt1e1/pmc93x6_eeprom.h
new file mode 100644 (file)
index 0000000..c3ada87
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * $Id: pmc93x6_eeprom.h,v 1.1 2005/09/28 00:10:08 rickd PMCC4_3_1B $
+ */
+
+#ifndef _INC_PMC93X6_EEPROM_H_
+#define _INC_PMC93X6_EEPROM_H_
+
+/*-----------------------------------------------------------------------------
+ * pmc93x6_eeprom.h -
+ *
+ * Copyright (C) 2002-2004  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@sbei.com
+ * SBE, Inc.  San Ramon, California  U.S.A.
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ *-----------------------------------------------------------------------------
+ * $Log: pmc93x6_eeprom.h,v $
+ * Revision 1.1  2005/09/28 00:10:08  rickd
+ * pmc_verify_cksum return value is char.
+ *
+ * Revision 1.0  2005/05/04 17:20:51  rickd
+ * Initial revision
+ *
+ * Revision 1.0  2005/04/22 23:48:48  rickd
+ * Initial revision
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#if defined (__FreeBSD__) || defined (__NetBSD__)
+#include <sys/types.h>
+#else
+#include <linux/types.h>
+#endif
+
+#ifdef __KERNEL__
+
+#include "pmcc4_private.h"
+
+void        pmc_eeprom_read_buffer (long, long, char *, int);
+void        pmc_eeprom_write_buffer (long, long, char *, int);
+void        pmc_init_seeprom (u_int32_t, u_int32_t);
+char        pmc_verify_cksum (void *);
+
+#endif    /*** __KERNEL__ ***/
+
+#endif
+
+/*** End-of-File ***/
diff --git a/drivers/staging/cxt1e1/pmcc4.h b/drivers/staging/cxt1e1/pmcc4.h
new file mode 100644 (file)
index 0000000..26c1f0e
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * $Id: pmcc4.h,v 1.4 2005/11/01 19:24:48 rickd PMCC4_3_1B $
+ */
+
+#ifndef _INC_PMCC4_H_
+#define _INC_PMCC4_H_
+
+/*-----------------------------------------------------------------------------
+ * pmcc4.h -
+ *
+ * Copyright (C) 2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@sbei.com
+ * SBE, Inc.  San Ramon, California  U.S.A.
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 1.4 $
+ * Last changed on $Date: 2005/11/01 19:24:48 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: pmcc4.h,v $
+ * Revision 1.4  2005/11/01 19:24:48  rickd
+ * Remove de-implement function prototypes.  Several <int> to
+ * <status_t> changes for consistant usage of same.
+ *
+ * Revision 1.3  2005/09/28 00:10:08  rickd
+ * Add GNU license info. Use config params from libsbew.h
+ *
+ * Revision 1.2  2005/04/28 23:43:03  rickd
+ * Add RCS tracking heading.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+#include <sys/types.h>
+#else
+#ifndef __KERNEL__
+#include <sys/types.h>
+#else
+#include <linux/types.h>
+#endif
+#endif
+
+
+
+typedef int status_t;
+
+#define SBE_DRVR_FAIL     0
+#define SBE_DRVR_SUCCESS  1
+
+#ifdef __cplusplus
+extern      "C"
+{
+#endif
+
+
+/********************/
+/* PMCC4 memory Map */
+/********************/
+
+#define COMET_OFFSET(x) (0x80000+(x)*0x10000)
+#define EEPROM_OFFSET   0xC0000
+#define CPLD_OFFSET     0xD0000
+
+    struct pmcc4_timeslot_param
+    {
+        u_int8_t    card;       /* the card number */
+        u_int8_t    port;       /* the port number */
+        u_int8_t    _reserved1;
+        u_int8_t    _reserved2;
+
+        /*
+         * each byte in bitmask below represents one timeslot (bitmask[0] is
+         * for timeslot 0 and so on), each bit in the byte selects timeslot
+         * bits for this channel (0xff - whole timeslot, 0x7f - 56kbps mode)
+         */
+        u_int8_t    bitmask[32];
+    };
+
+    struct c4_musycc_param
+    {
+        u_int8_t    RWportnum;
+                    u_int16_t offset;
+        u_int32_t   value;
+    };
+
+/*Alarm values */
+#define sbeE1RMAI      0x100
+#define sbeYelAlm      0x04
+#define sbeRedAlm      0x02
+#define sbeAISAlm      0x01
+
+#define sbeE1errSMF    0x02
+#define sbeE1CRC       0x01
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __KERNEL__
+
+/*
+ * Device Driver interface, routines are for internal use only.
+ */
+
+#include "pmcc4_private.h"
+
+#if !(LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+char       *get_hdlc_name (hdlc_device *);
+
+#endif
+
+
+/*
+ * external interface
+ */
+
+void        c4_cleanup (void);
+status_t    c4_chan_up (ci_t *, int channum);
+status_t    c4_del_chan_stats (int channum);
+status_t    c4_del_chan (int channum);
+status_t    c4_get_iidinfo (ci_t * ci, struct sbe_iid_info * iip);
+int         c4_is_chan_up (int channum);
+
+void       *getuserbychan (int channum);
+void        pci_flush_write (ci_t * ci);
+void        sbecom_set_loglevel (int debuglevel);
+char       *sbeid_get_bdname (ci_t * ci);
+void        sbeid_set_bdtype (ci_t * ci);
+void        sbeid_set_hdwbid (ci_t * ci);
+u_int32_t   sbeCrc (u_int8_t *, u_int32_t, u_int32_t, u_int32_t *);
+
+void        VMETRO_TRACE (void *);       /* put data into 8 LEDs */
+void        VMETRO_TRIGGER (ci_t *, int);       /* Note: int = 0(default)
+                                                 * thru 15 */
+
+#if defined (SBE_ISR_TASKLET)
+void        musycc_intr_bh_tasklet (ci_t *);
+
+#endif
+
+#endif                          /*** __KERNEL __ ***/
+#endif                          /* _INC_PMCC4_H_ */
diff --git a/drivers/staging/cxt1e1/pmcc4_cpld.h b/drivers/staging/cxt1e1/pmcc4_cpld.h
new file mode 100644 (file)
index 0000000..6d8f033
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * $Id: pmcc4_cpld.h,v 1.0 2005/09/28 00:10:08 rickd PMCC4_3_1B $
+ */
+
+#ifndef _INC_PMCC4_CPLD_H_
+#define _INC_PMCC4_CPLD_H_
+
+/*-----------------------------------------------------------------------------
+ * pmcc4_cpld.h -
+ *
+ * Copyright (C) 2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@sbei.com
+ * SBE, Inc.  San Ramon, California  U.S.A.
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 1.0 $
+ * Last changed on $Date: 2005/09/28 00:10:08 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: pmcc4_cpld.h,v $
+ * Revision 1.0  2005/09/28 00:10:08  rickd
+ * Initial revision
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+#include <sys/types.h>
+#else
+#ifndef __KERNEL__
+#include <sys/types.h>
+#else
+#include <linux/types.h>
+#endif
+#endif
+
+#ifdef __cplusplus
+extern      "C"
+{
+#endif
+
+
+/********************************/
+/* iSPLD control chip registers */
+/********************************/
+
+#if 0
+#define CPLD_MCSR    0x0
+#define CPLD_MCLK    0x1
+#define CPLD_LEDS    0x2
+#define CPLD_INTR    0x3
+#endif
+
+    struct c4_cpld
+    {
+        volatile u_int32_t mcsr;/* r/w: Master Clock Source Register */
+        volatile u_int32_t mclk;/* r/w: Master Clock Register */
+        volatile u_int32_t leds;/* r/w: LED Register */
+        volatile u_int32_t intr;/* r: Interrupt Register */
+    };
+
+    typedef struct c4_cpld c4cpld_t;
+
+/* mcsr note: sourcing COMET must be initialized to Master Mode */
+#define PMCC4_CPLD_MCSR_IND     0       /* ports used individual BP Clk as
+                                         * source, no slaves */
+#define PMCC4_CPLD_MCSR_CMT_1   1       /* COMET 1 BP Clk is source, 2,3,4
+                                         * are Clk slaves */
+#define PMCC4_CPLD_MCSR_CMT_2   2       /* COMET 2 BP Clk is source, 1,3,4
+                                         * are Clk slaves */
+#define PMCC4_CPLD_MCSR_CMT_3   3       /* COMET 3 BP Clk is source, 1,2,4
+                                         * are Clk slaves */
+#define PMCC4_CPLD_MCSR_CMT_4   4       /* COMET 4 BP Clk is source, 1,2,3
+                                         * are Clk slaves */
+
+#define PMCC4_CPLD_MCLK_MASK    0x0f
+#define PMCC4_CPLD_MCLK_P1      0x1
+#define PMCC4_CPLD_MCLK_P2      0x2
+#define PMCC4_CPLD_MCLK_P3      0x4
+#define PMCC4_CPLD_MCLK_P4      0x8
+#define PMCC4_CPLD_MCLK_T1      0x00
+#define PMCC4_CPLD_MCLK_P1_E1   0x01
+#define PMCC4_CPLD_MCLK_P2_E1   0x02
+#define PMCC4_CPLD_MCLK_P3_E1   0x04
+#define PMCC4_CPLD_MCLK_P4_E1   0x08
+
+#define PMCC4_CPLD_LED_OFF      0
+#define PMCC4_CPLD_LED_ON       1
+#define PMCC4_CPLD_LED_GP0      0x01    /* port 0, green  */
+#define PMCC4_CPLD_LED_YP0      0x02    /* port 0, yellow */
+#define PMCC4_CPLD_LED_GP1      0x04    /* port 1, green  */
+#define PMCC4_CPLD_LED_YP1      0x08    /* port 1, yellow */
+#define PMCC4_CPLD_LED_GP2      0x10    /* port 2, green  */
+#define PMCC4_CPLD_LED_YP2      0x20    /* port 2, yellow */
+#define PMCC4_CPLD_LED_GP3      0x40    /* port 3, green  */
+#define PMCC4_CPLD_LED_YP3      0x80    /* port 3, yellow */
+#define PMCC4_CPLD_LED_GREEN   (PMCC4_CPLD_LED_GP0 | PMCC4_CPLD_LED_GP1 | \
+                                PMCC4_CPLD_LED_GP2 | PMCC4_CPLD_LED_GP3 )
+#define PMCC4_CPLD_LED_YELLOW  (PMCC4_CPLD_LED_YP0 | PMCC4_CPLD_LED_YP1 | \
+                                PMCC4_CPLD_LED_YP2 | PMCC4_CPLD_LED_YP3)
+
+#define PMCC4_CPLD_INTR_MASK    0x0f
+#define PMCC4_CPLD_INTR_CMT_1   0x01
+#define PMCC4_CPLD_INTR_CMT_2   0x02
+#define PMCC4_CPLD_INTR_CMT_3   0x04
+#define PMCC4_CPLD_INTR_CMT_4   0x08
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif                          /* _INC_PMCC4_CPLD_H_ */
diff --git a/drivers/staging/cxt1e1/pmcc4_defs.h b/drivers/staging/cxt1e1/pmcc4_defs.h
new file mode 100644 (file)
index 0000000..186347b
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * $Id: pmcc4_defs.h,v 1.0 2005/09/28 00:10:09 rickd PMCC4_3_1B $
+ */
+
+#ifndef _INC_PMCC4_DEFS_H_
+#define _INC_PMCC4_DEFS_H_
+
+/*-----------------------------------------------------------------------------
+ * c4_defs.h -
+ *
+ *   Implementation elements of the wanPMC-C4T1E1 device driver
+ *
+ * Copyright (C) 2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@sbei.com
+ * SBE, Inc.  San Ramon, California  U.S.A.
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 1.0 $
+ * Last changed on $Date: 2005/09/28 00:10:09 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: pmcc4_defs.h,v $
+ * Revision 1.0  2005/09/28 00:10:09  rickd
+ * Initial revision
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+#define MAX_BOARDS          8
+#define MAX_CHANS_USED      128
+
+#ifdef  SBE_PMCC4_ENABLE
+#define MUSYCC_NPORTS       4     /* CN8474 */
+#endif
+#ifdef SBE_WAN256T3_ENABLE
+#define MUSYCC_NPORTS       8     /* CN8478 */
+#endif
+#define MUSYCC_NCHANS       32    /* actually, chans per port */
+
+#define MUSYCC_NIQD         0x1000    /* power of 2 */
+#define MUSYCC_MRU          2048  /* default */
+#define MUSYCC_MTU          2048  /* default */
+#define MUSYCC_TXDESC_MIN   10    /* HDLC mode default */
+#define MUSYCC_RXDESC_MIN   18    /* HDLC mode default */
+#define MUSYCC_TXDESC_TRANS 4     /* Transparent mode minumum # of TX descriptors */
+#define MUSYCC_RXDESC_TRANS 12    /* Transparent mode minumum # of RX descriptors */
+
+#define MAX_DEFAULT_IFQLEN  32    /* network qlen */
+
+
+#define SBE_IFACETMPL        "pmcc4-%d"
+#ifdef IFNAMSIZ
+#define SBE_IFACETMPL_SIZE    IFNAMSIZ
+#else
+#define SBE_IFACETMPL_SIZE    16
+#endif
+
+/* we want the PMCC4 watchdog to fire off every 250ms */
+#define WATCHDOG_TIMEOUT      250000
+
+/* if we restart the watchdog every 250ms, then we'll time out
+ * an additional 300ms later */
+#define WATCHDOG_UTIMEOUT     (WATCHDOG_TIMEOUT+300000)
+
+#if !defined(SBE_ISR_TASKLET) && !defined(SBE_ISR_IMMEDIATE) && !defined(SBE_ISR_INLINE)
+#define SBE_ISR_TASKLET
+#endif
+
+#endif   /*** _INC_PMCC4_DEFS_H_ ***/
+
diff --git a/drivers/staging/cxt1e1/pmcc4_drv.c b/drivers/staging/cxt1e1/pmcc4_drv.c
new file mode 100644 (file)
index 0000000..ada80d0
--- /dev/null
@@ -0,0 +1,1855 @@
+/*
+ * $Id: pmcc4_drv.c,v 3.1 2007/08/15 23:32:17 rickd PMCC4_3_1B $
+ */
+
+
+/*-----------------------------------------------------------------------------
+ * pmcc4_drv.c -
+ *
+ * Copyright (C) 2007  One Stop Systems, Inc.
+ * Copyright (C) 2002-2006  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@onestopsystems.com
+ * One Stop Systems, Inc.  Escondido, California  U.S.A.
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 3.1 $
+ * Last changed on $Date: 2007/08/15 23:32:17 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: pmcc4_drv.c,v $
+ * Revision 3.1  2007/08/15 23:32:17  rickd
+ * Use 'if 0' instead of GNU comment delimeter to avoid line wrap induced compiler errors.
+ *
+ * Revision 3.0  2007/08/15 22:19:55  rickd
+ * Correct sizeof() castings and pi->regram to support 64bit compatibility.
+ *
+ * Revision 2.10  2006/04/21 00:56:40  rickd
+ * workqueue files now prefixed with <sbecom> prefix.
+ *
+ * Revision 2.9  2005/11/01 19:22:49  rickd
+ * Add sanity checks against max_port for ioctl functions.
+ *
+ * Revision 2.8  2005/10/27 18:59:25  rickd
+ * Code cleanup.  Default channel config to HDLC_FCS16.
+ *
+ * Revision 2.7  2005/10/18 18:16:30  rickd
+ * Further NCOMM code repairs - (1) interrupt matrix usage inconsistant
+ * for indexing into nciInterrupt[][], code missing double parameters.
+ * (2) check input of ncomm interrupt registration cardID for correct
+ * boundary values.
+ *
+ * Revision 2.6  2005/10/17 23:55:28  rickd
+ * Initial port of NCOMM support patches from original work found
+ * in pmc_c4t1e1 as updated by NCOMM.  Ref: CONFIG_SBE_PMCC4_NCOMM.
+ * Corrected NCOMMs wanpmcC4T1E1_getBaseAddress() to correctly handle
+ * multiple boards.
+ *
+ * Revision 2.5  2005/10/13 23:01:28  rickd
+ * Correct panic for illegal address reference w/in get_brdinfo on
+ * first_if/last_if name acquistion under Linux 2.6
+ *
+ * Revision 2.4  2005/10/13 21:20:19  rickd
+ * Correction of c4_cleanup() wherein next should be acquired before
+ * ci_t structure is free'd.
+ *
+ * Revision 2.3  2005/10/13 19:20:10  rickd
+ * Correct driver removal cleanup code for multiple boards.
+ *
+ * Revision 2.2  2005/10/11 18:34:04  rickd
+ * New routine added to determine number of ports (comets) on board.
+ *
+ * Revision 2.1  2005/10/05 00:48:13  rickd
+ * Add some RX activation trace code.
+ *
+ * Revision 2.0  2005/09/28 00:10:06  rickd
+ * Implement 2.6 workqueue for TX/RX restart.  Correction to
+ * hardware register boundary checks allows expanded access of MUSYCC.
+ * Implement new musycc reg&bits namings.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+char        OSSIid_pmcc4_drvc[] =
+"@(#)pmcc4_drv.c - $Revision: 3.1 $   (c) Copyright 2002-2007 One Stop Systems, Inc.";
+
+
+#if defined (__FreeBSD__) || defined (__NetBSD__)
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#else
+#include <linux/types.h>
+#include "pmcc4_sysdep.h"
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>        /* include for timer */
+#include <linux/timer.h>        /* include for timer */
+#include <linux/hdlc.h>
+#include <asm/io.h>
+#endif
+
+#include "sbecom_inline_linux.h"
+#include "libsbew.h"
+#include "pmcc4_private.h"
+#include "pmcc4.h"
+#include "pmcc4_ioctls.h"
+#include "musycc.h"
+#include "comet.h"
+#include "sbe_bid.h"
+
+#ifdef SBE_INCLUDE_SYMBOLS
+#define STATIC
+#else
+#define STATIC  static
+#endif
+
+
+#define KERN_WARN KERN_WARNING
+
+/* forward references */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
+status_t    c4_wk_chan_init (mpi_t *, mch_t *);
+void        c4_wq_port_cleanup (mpi_t *);
+status_t    c4_wq_port_init (mpi_t *);
+
+#endif
+int         c4_loop_port (ci_t *, int, u_int8_t);
+status_t    c4_set_port (ci_t *, int);
+status_t    musycc_chan_down (ci_t *, int);
+
+u_int32_t musycc_chan_proto (int);
+status_t    musycc_dump_ring (ci_t *, unsigned int);
+status_t __init musycc_init (ci_t *);
+void        musycc_init_mdt (mpi_t *);
+void        musycc_serv_req (mpi_t *, u_int32_t);
+void        musycc_update_timeslots (mpi_t *);
+
+extern void musycc_update_tx_thp (mch_t *);
+extern int  log_level;
+extern int  max_mru;
+extern int  max_mtu;
+extern int  max_rxdesc_used, max_rxdesc_default;
+extern int  max_txdesc_used, max_txdesc_default;
+
+#if defined (__powerpc__)
+extern void *memset (void *s, int c, size_t n);
+
+#endif
+
+int         drvr_state = SBE_DRVR_INIT;
+ci_t       *c4_list = 0;
+ci_t       *CI;                 /* dummy pointer to board ZEROE's data -
+                                 * DEBUG USAGE */
+
+
+void
+sbecom_set_loglevel (int d)
+{
+    /*
+     * The code within the following -if- clause is a backdoor debug facility
+     * which can be used to display the state of a board's channel.
+     */
+    if (d > LOG_DEBUG)
+    {
+        unsigned int channum = d - (LOG_DEBUG + 1);     /* convert to ZERO
+                                                         * relativity */
+
+        (void) musycc_dump_ring ((ci_t *) CI, channum); /* CI implies support
+                                                         * for card 0 only */
+    } else
+    {
+        if (log_level != d)
+        {
+            printk ("%s: log level changed from %d to %d\n", THIS_MODULE->name, log_level, d);
+            log_level = d;          /* set new */
+        } else
+            printk ("%s: log level is %d\n", THIS_MODULE->name, log_level);
+    }
+}
+
+
+mch_t      *
+c4_find_chan (int channum)
+{
+    ci_t       *ci;
+    mch_t      *ch;
+    int         portnum, gchan;
+
+    for (ci = c4_list; ci; ci = ci->next)
+        for (portnum = 0; portnum < ci->max_port; portnum++)
+            for (gchan = 0; gchan < MUSYCC_NCHANS; gchan++)
+            {
+                if ((ch = ci->port[portnum].chan[gchan]))
+                {
+                    if ((ch->state != UNASSIGNED) &&
+                        (ch->channum == channum))
+                        return (ch);
+                }
+            }
+    return 0;
+}
+
+
+ci_t       *__init
+c4_new (void *hi)
+{
+    ci_t       *ci;
+
+#ifdef SBE_MAP_DEBUG
+    printk (KERN_WARNING "%s: c4_new() entered, ci needs %u.\n",
+            THIS_MODULE->name, (unsigned int) sizeof (ci_t));
+#endif
+
+    ci = (ci_t *) OS_kmalloc (sizeof (ci_t));
+    if (ci)
+    {
+        ci->hdw_info = hi;
+        ci->state = C_INIT;         /* mark as hardware not available */
+        ci->next = c4_list;
+        c4_list = ci;
+        ci->brdno = ci->next ? ci->next->brdno + 1 : 0;
+    } else
+        printk (KERN_WARNING "%s: failed CI malloc, size %u.\n",
+                THIS_MODULE->name, (unsigned int) sizeof (ci_t));
+
+    if (CI == 0)
+        CI = ci;                    /* DEBUG, only board 0 usage */
+    return ci;
+}
+
+
+/***
+ * Check port state and set LED states using watchdog or ioctl...
+ * also check for in-band SF loopback commands (& cause results if they are there)
+ *
+ * Alarm function depends on comet bits indicating change in
+ * link status (linkMask) to keep the link status indication straight.
+ *
+ * Indications are only LED and system log -- except when ioctl is invoked.
+ *
+ * "alarmed" record (a.k.a. copyVal, in some cases below) decodes as:
+ *
+ *   RMAI  (E1 only) 0x100
+ *   alarm LED on    0x80
+ *   link LED on     0x40
+ *   link returned   0x20 (link was down, now it's back and 'port get' hasn't run)
+ *   change in LED   0x10 (update LED register because value has changed)
+ *   link is down    0x08
+ *   YelAlm(RAI)     0x04
+ *   RedAlm          0x02
+ *   AIS(blue)Alm    0x01
+ *
+ * note "link has returned" indication is reset on read
+ * (e.g. by use of the c4_control port get command)
+ */
+
+#define sbeLinkMask       0x41  /* change in signal status (lost/recovered) +
+                                 * state */
+#define sbeLinkChange     0x40
+#define sbeLinkDown       0x01
+#define sbeAlarmsMask     0x07  /* red / yellow / blue alarm conditions */
+#define sbeE1AlarmsMask   0x107 /* alarm conditions */
+
+#define COMET_LBCMD_READ  0x80  /* read only (do not set, return read value) */
+
+void
+checkPorts (ci_t * ci)
+{
+#ifndef CONFIG_SBE_PMCC4_NCOMM
+    /*
+     * PORT POINT - NCOMM needs to avoid this code since the polling of
+     * alarms conflicts with NCOMM's interrupt servicing implementation.
+     */
+
+    comet_t    *comet;
+    volatile u_int32_t value;
+    u_int32_t   copyVal, LEDval;
+
+    u_int8_t portnum;
+
+    LEDval = 0;
+    for (portnum = 0; portnum < ci->max_port; portnum++)
+    {
+        copyVal = 0x12f & (ci->alarmed[portnum]);       /* port's alarm record */
+        comet = ci->port[portnum].cometbase;
+        value = pci_read_32 ((u_int32_t *) &comet->cdrc_ists) & sbeLinkMask;    /* link loss reg */
+
+        if (value & sbeLinkChange)  /* is there a change in the link stuff */
+        {
+            /* if there's been a change (above) and yet it's the same (below) */
+            if (!(((copyVal >> 3) & sbeLinkDown) ^ (value & sbeLinkDown)))
+            {
+                if (value & sbeLinkDown)
+                    printk (KERN_WARN "%s: Port %d momentarily recovered.\n",
+                            ci->devname, portnum);
+                else
+                    printk (KERN_WARN
+                            "%s: Warning: Port %d link was briefly down.\n",
+                            ci->devname, portnum);
+            } else if (value & sbeLinkDown)
+                printk (KERN_WARN "%s: Warning: Port %d link is down.\n",
+                        ci->devname, portnum);
+            else
+            {
+                printk (KERN_WARN "%s: Port %d link has recovered.\n",
+                        ci->devname, portnum);
+                copyVal |= 0x20;    /* record link transition to up */
+            }
+            copyVal |= 0x10;        /* change (link) --> update LEDs  */
+        }
+        copyVal &= 0x137;           /* clear LED & link old history bits &
+                                     * save others */
+        if (value & sbeLinkDown)
+            copyVal |= 0x08;        /* record link status (now) */
+        else
+        {                           /* if link is up, do this */
+            copyVal |= 0x40;        /* LED indicate link is up    */
+            /* Alarm things & the like ... first if E1, then if T1 */
+            if (IS_FRAME_ANY_E1 (ci->port[portnum].p.port_mode))
+            {
+                /*
+                 * first check Codeword (SaX) changes & CRC and
+                 * sub-multi-frame errors
+                 */
+                /*
+                 * note these errors are printed every time they are detected
+                 * vs. alarms
+                 */
+                value = pci_read_32 ((u_int32_t *) &comet->e1_frmr_nat_ists);   /* codeword */
+                if (value & 0x1f)
+                {                   /* if errors (crc or smf only) */
+                    if (value & 0x10)
+                        printk (KERN_WARN
+                           "%s: E1 Port %d Codeword Sa4 change detected.\n",
+                                ci->devname, portnum);
+                    if (value & 0x08)
+                        printk (KERN_WARN
+                           "%s: E1 Port %d Codeword Sa5 change detected.\n",
+                                ci->devname, portnum);
+                    if (value & 0x04)
+                        printk (KERN_WARN
+                           "%s: E1 Port %d Codeword Sa6 change detected.\n",
+                                ci->devname, portnum);
+                    if (value & 0x02)
+                        printk (KERN_WARN
+                           "%s: E1 Port %d Codeword Sa7 change detected.\n",
+                                ci->devname, portnum);
+                    if (value & 0x01)
+                        printk (KERN_WARN
+                           "%s: E1 Port %d Codeword Sa8 change detected.\n",
+                                ci->devname, portnum);
+                }
+                value = pci_read_32 ((u_int32_t *) &comet->e1_frmr_mists);      /* crc & smf */
+                if (value & 0x3)
+                {                   /* if errors (crc or smf only) */
+                    if (value & sbeE1CRC)
+                        printk (KERN_WARN "%s: E1 Port %d CRC-4 error(s) detected.\n",
+                                ci->devname, portnum);
+                    if (value & sbeE1errSMF)    /* error in sub-multiframe */
+                        printk (KERN_WARN "%s: E1 Port %d received errored SMF.\n",
+                                ci->devname, portnum);
+                }
+                value = pci_read_32 ((u_int32_t *) &comet->e1_frmr_masts) & 0xcc; /* alarms */
+                /*
+                 * pack alarms together (bitmiser), and construct similar to
+                 * T1
+                 */
+                /* RAI,RMAI,.,.,LOF,AIS,.,. ==>  RMAI,.,.,.,.,.,RAI,LOF,AIS */
+                /* see 0x97 */
+                value = (value >> 2);
+                if (value & 0x30)
+                {
+                    if (value & 0x20)
+                        value |= 0x40;  /* RAI */
+                    if (value & 0x10)
+                        value |= 0x100; /* RMAI */
+                    value &= ~0x30;
+                }                   /* finished packing alarm in handy order */
+                if (value != (copyVal & sbeE1AlarmsMask))
+                {                   /* if alarms changed */
+                    copyVal |= 0x10;/* change LED status   */
+                    if ((copyVal & sbeRedAlm) && !(value & sbeRedAlm))
+                    {
+                        copyVal &= ~sbeRedAlm;
+                        printk (KERN_WARN "%s: E1 Port %d LOF alarm ended.\n",
+                                ci->devname, portnum);
+                    } else if (!(copyVal & sbeRedAlm) && (value & sbeRedAlm))
+                    {
+                        copyVal |= sbeRedAlm;
+                        printk (KERN_WARN "%s: E1 Warning: Port %d LOF alarm.\n",
+                                ci->devname, portnum);
+                    } else if ((copyVal & sbeYelAlm) && !(value & sbeYelAlm))
+                    {
+                        copyVal &= ~sbeYelAlm;
+                        printk (KERN_WARN "%s: E1 Port %d RAI alarm ended.\n",
+                                ci->devname, portnum);
+                    } else if (!(copyVal & sbeYelAlm) && (value & sbeYelAlm))
+                    {
+                        copyVal |= sbeYelAlm;
+                        printk (KERN_WARN "%s: E1 Warning: Port %d RAI alarm.\n",
+                                ci->devname, portnum);
+                    } else if ((copyVal & sbeE1RMAI) && !(value & sbeE1RMAI))
+                    {
+                        copyVal &= ~sbeE1RMAI;
+                        printk (KERN_WARN "%s: E1 Port %d RMAI alarm ended.\n",
+                                ci->devname, portnum);
+                    } else if (!(copyVal & sbeE1RMAI) && (value & sbeE1RMAI))
+                    {
+                        copyVal |= sbeE1RMAI;
+                        printk (KERN_WARN "%s: E1 Warning: Port %d RMAI alarm.\n",
+                                ci->devname, portnum);
+                    } else if ((copyVal & sbeAISAlm) && !(value & sbeAISAlm))
+                    {
+                        copyVal &= ~sbeAISAlm;
+                        printk (KERN_WARN "%s: E1 Port %d AIS alarm ended.\n",
+                                ci->devname, portnum);
+                    } else if (!(copyVal & sbeAISAlm) && (value & sbeAISAlm))
+                    {
+                        copyVal |= sbeAISAlm;
+                        printk (KERN_WARN "%s: E1 Warning: Port %d AIS alarm.\n",
+                                ci->devname, portnum);
+                    }
+                }
+                /* end of E1 alarm code */
+            } else
+            {                       /* if a T1 mode */
+                value = pci_read_32 ((u_int32_t *) &comet->t1_almi_ists);       /* alarms */
+                value &= sbeAlarmsMask;
+                if (value != (copyVal & sbeAlarmsMask))
+                {                   /* if alarms changed */
+                    copyVal |= 0x10;/* change LED status   */
+                    if ((copyVal & sbeRedAlm) && !(value & sbeRedAlm))
+                    {
+                        copyVal &= ~sbeRedAlm;
+                        printk (KERN_WARN "%s: Port %d red alarm ended.\n",
+                                ci->devname, portnum);
+                    } else if (!(copyVal & sbeRedAlm) && (value & sbeRedAlm))
+                    {
+                        copyVal |= sbeRedAlm;
+                        printk (KERN_WARN "%s: Warning: Port %d red alarm.\n",
+                                ci->devname, portnum);
+                    } else if ((copyVal & sbeYelAlm) && !(value & sbeYelAlm))
+                    {
+                        copyVal &= ~sbeYelAlm;
+                        printk (KERN_WARN "%s: Port %d yellow (RAI) alarm ended.\n",
+                                ci->devname, portnum);
+                    } else if (!(copyVal & sbeYelAlm) && (value & sbeYelAlm))
+                    {
+                        copyVal |= sbeYelAlm;
+                        printk (KERN_WARN "%s: Warning: Port %d yellow (RAI) alarm.\n",
+                                ci->devname, portnum);
+                    } else if ((copyVal & sbeAISAlm) && !(value & sbeAISAlm))
+                    {
+                        copyVal &= ~sbeAISAlm;
+                        printk (KERN_WARN "%s: Port %d blue (AIS) alarm ended.\n",
+                                ci->devname, portnum);
+                    } else if (!(copyVal & sbeAISAlm) && (value & sbeAISAlm))
+                    {
+                        copyVal |= sbeAISAlm;
+                        printk (KERN_WARN "%s: Warning: Port %d blue (AIS) alarm.\n",
+                                ci->devname, portnum);
+                    }
+                }
+            }                       /* end T1 mode alarm checks */
+        }
+        if (copyVal & sbeAlarmsMask)
+            copyVal |= 0x80;        /* if alarm turn yel LED on */
+        if (copyVal & 0x10)
+            LEDval |= 0x100;        /* tag if LED values have changed  */
+        LEDval |= ((copyVal & 0xc0) >> (6 - (portnum * 2)));
+
+        ci->alarmed[portnum] &= 0xfffff000;     /* out with the old (it's fff
+                                                 * ... foo) */
+        ci->alarmed[portnum] |= (copyVal);      /* in with the new */
+
+        /*
+         * enough with the alarms and LED's, now let's check for loopback
+         * requests
+         */
+
+        if (IS_FRAME_ANY_T1 (ci->port[portnum].p.port_mode))
+        {                           /* if a T1 mode  */
+            /*
+             * begin in-band (SF) loopback code detection -- start by reading
+             * command
+             */
+            value = pci_read_32 ((u_int32_t *) &comet->ibcd_ies);       /* detect reg. */
+            value &= 0x3;           /* trim to handy bits */
+            if (value & 0x2)
+            {                       /* activate loopback (sets for deactivate
+                                     * code length) */
+                copyVal = c4_loop_port (ci, portnum, COMET_LBCMD_READ); /* read line loopback
+                                                                         * mode */
+                if (copyVal != COMET_MDIAG_LINELB)      /* don't do it again if
+                                                         * already in that mode */
+                    c4_loop_port (ci, portnum, COMET_MDIAG_LINELB);     /* put port in line
+                                                                         * loopback mode */
+            }
+            if (value & 0x1)
+            {                       /* deactivate loopback (sets for activate
+                                     * code length) */
+                copyVal = c4_loop_port (ci, portnum, COMET_LBCMD_READ); /* read line loopback
+                                                                         * mode */
+                if (copyVal != COMET_MDIAG_LBOFF)       /* don't do it again if
+                                                         * already in that mode */
+                    c4_loop_port (ci, portnum, COMET_MDIAG_LBOFF);      /* take port out of any
+                                                                         * loopback mode */
+            }
+        }
+        if (IS_FRAME_ANY_T1ESF (ci->port[portnum].p.port_mode))
+        {                           /* if a T1 ESF mode  */
+            /* begin ESF loopback code */
+            value = pci_read_32 ((u_int32_t *) &comet->t1_rboc_sts) & 0x3f;     /* read command */
+            if (value == 0x07)
+                c4_loop_port (ci, portnum, COMET_MDIAG_LINELB); /* put port in line
+                                                                 * loopback mode */
+            if (value == 0x0a)
+                c4_loop_port (ci, portnum, COMET_MDIAG_PAYLB);  /* put port in payload
+                                                                 * loopbk mode */
+            if ((value == 0x1c) || (value == 0x19) || (value == 0x12))
+                c4_loop_port (ci, portnum, COMET_MDIAG_LBOFF);  /* take port out of any
+                                                                 * loopbk mode */
+            if (log_level >= LOG_DEBUG)
+                if (value != 0x3f)
+                    printk (KERN_WARN "%s: BOC value = %x on Port %d\n",
+                            ci->devname, value, portnum);
+            /* end ESF loopback code */
+        }
+    }
+
+    /* if something is new, update LED's */
+    if (LEDval & 0x100)
+        pci_write_32 ((u_int32_t *) &ci->cpldbase->leds, LEDval & 0xff);
+#endif                              /*** CONFIG_SBE_PMCC4_NCOMM ***/
+}
+
+
+STATIC void
+c4_watchdog (ci_t * ci)
+{
+#if 0
+    //unsigned long flags;
+#endif
+
+    if (drvr_state != SBE_DRVR_AVAILABLE)
+    {
+        if (log_level >= LOG_MONITOR)
+            printk ("%s: drvr not available (%x)\n", THIS_MODULE->name, drvr_state);
+        return;
+    }
+#if 0
+    SD_SEM_TAKE (&ci->sem_wdbusy, "_wd_");    /* only 1 thru here, per
+                                               * board */
+#endif
+
+    ci->wdcount++;
+    checkPorts (ci);
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,41)
+    if (ci->wd_notify)
+    {                               /* is there a state change to search for */
+        int         port, gchan;
+
+        ci->wd_notify = 0;          /* reset notification */
+        for (gchan = 0; gchan < MUSYCC_NCHANS; gchan++)
+        {
+            for (port = 0; port < ci->max_port; port++)
+            {
+                mch_t      *ch = ci->port[port].chan[gchan];
+
+                if (!ch || ci->state != C_RUNNING)      /* state changed while
+                                                         * acquiring semaphore */
+                    break;
+                if (ch->state == UP)/* channel must be set up */
+                {
+#if 0
+#ifdef RLD_TRANS_DEBUG
+                    if (1 || log_level >= LOG_MONITOR)
+#else
+                    if (log_level >= LOG_MONITOR)
+#endif
+                        printk ("%s: watchdog reviving Port %d Channel %d [%d] sts %x/%x, start_TX %x free %x start_RX %x\n",
+                         ci->devname, ch->channum, port, gchan, ch->channum,
+                                ch->p.status, ch->status,
+                            ch->ch_start_tx, ch->txd_free, ch->ch_start_rx);
+#endif
+
+                    /**********************************/
+                    /** check for RX restart request **/
+                    /**********************************/
+
+                    if (ch->ch_start_rx &&
+                        (ch->status & RX_ENABLED))      /* requires start on
+                                                         * enabled RX */
+                    {
+                        ch->ch_start_rx = 0;    /* we are restarting RX... */
+#ifdef RLD_TRANS_DEBUG
+                        printk ("++ c4_watchdog() CHAN RX ACTIVATE: chan %d\n", ch->channum);
+#endif
+#ifdef RLD_RXACT_DEBUG
+                        {
+                            struct mdesc *md;
+                            static int  hereb4 = 7;
+
+                            if (hereb4)
+                            {
+                                hereb4--;
+                                md = &ch->mdr[ch->rxix_irq_srv];
+                                printk ("++ c4_watchdog[%d] CHAN RX ACTIVATE: rxix_irq_srv %d, md %p sts %x, rxpkt %lu\n",
+                                        ch->channum, ch->rxix_irq_srv, md, le32_to_cpu (md->status), ch->s.rx_packets);
+                                musycc_dump_rxbuffer_ring (ch, 1);      /* RLD DEBUG */
+                            }
+                        }
+#endif
+                        musycc_serv_req (ch->up, SR_CHANNEL_ACTIVATE | SR_RX_DIRECTION | gchan);
+                    }
+                    /**********************************/
+                    /** check for TX restart request **/
+                    /**********************************/
+
+                    if (ch->ch_start_tx &&
+                        (ch->status & TX_ENABLED))      /* requires start on
+                                                         * enabled TX */
+                    {
+                        struct mdesc *md;
+
+                        /*
+                         * find next unprocessed message, then set TX thp to
+                         * it
+                         */
+                        musycc_update_tx_thp (ch);
+
+#if 0
+                        spin_lock_irqsave (&ch->ch_txlock, flags);
+#endif
+                        md = ch->txd_irq_srv;
+                        if (!md)
+                        {
+                            printk ("-- c4_watchdog[%d]: WARNING, starting NULL md\n", ch->channum);
+                            printk ("--   chan %d txd_irq_srv %p sts %x usr_add %p sts %x, txpkt %lu\n",
+                                    ch->channum, ch->txd_irq_srv, le32_to_cpu ((struct mdesc *) (ch->txd_irq_srv)->status),
+                                    ch->txd_usr_add, le32_to_cpu ((struct mdesc *) (ch->txd_usr_add)->status),
+                                    ch->s.tx_packets);
+#if 0
+                            spin_unlock_irqrestore (&ch->ch_txlock, flags);
+#endif
+                        } else if (md->data && ((le32_to_cpu (md->status)) & MUSYCC_TX_OWNED))
+                        {
+#ifdef RLD_TRANS_DEBUG
+                            printk ("++ c4_watchdog[%d] CHAN TX ACTIVATE: start_tx %x\n", ch->channum, ch->ch_start_tx);
+#endif
+                            ch->ch_start_tx = 0;        /* we are restarting
+                                                         * TX... */
+#if 0
+                            spin_unlock_irqrestore (&ch->ch_txlock, flags);   /* allow interrupts for
+                                                                               * service request */
+#endif
+                            musycc_serv_req (ch->up, SR_CHANNEL_ACTIVATE | SR_TX_DIRECTION | gchan);
+#ifdef RLD_TRANS_DEBUG
+                            if (1 || log_level >= LOG_MONITOR)
+#else
+                            if (log_level >= LOG_MONITOR)
+#endif
+                                printk ("++ SACK[P%d/C%d] ack'd, continuing...\n", ch->up->portnum, ch->channum);
+                        }
+                    }
+                }
+            }
+        }
+    }
+#else
+    ci->wd_notify = 0;
+#endif
+#if 0
+    SD_SEM_GIVE (&ci->sem_wdbusy);/* release per-board hold */
+#endif
+}
+
+
+void
+c4_cleanup (void)
+{
+    ci_t       *ci, *next;
+    mpi_t      *pi;
+    int         portnum, j;
+
+    ci = c4_list;
+    while (ci)
+    {
+        next = ci->next;            /* protect <next> from upcoming <free> */
+        pci_write_32 ((u_int32_t *) &ci->cpldbase->leds, PMCC4_CPLD_LED_OFF);
+        for (portnum = 0; portnum < ci->max_port; portnum++)
+        {
+            pi = &ci->port[portnum];
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
+            c4_wq_port_cleanup (pi);
+#endif
+            for (j = 0; j < MUSYCC_NCHANS; j++)
+            {
+                if (pi->chan[j])
+                    OS_kfree (pi->chan[j]);     /* free mch_t struct */
+            }
+            OS_kfree (pi->regram_saved);
+        }
+#if 0
+        /* obsolete - watchdog is now static w/in ci_t */
+        OS_free_watchdog (ci->wd);
+#endif
+        OS_kfree (ci->iqd_p_saved);
+        OS_kfree (ci);
+        ci = next;                  /* cleanup next board, if any */
+    }
+}
+
+
+/*
+ * This function issues a write to all comet chips and expects the same data
+ * to be returned from the subsequent read.  This determines the board build
+ * to be a 1-port, 2-port, or 4-port build.  The value returned represents a
+ * bit-mask of the found ports.  Only certain configurations are considered
+ * VALID or LEGAL builds.
+ */
+
+int
+c4_get_portcfg (ci_t * ci)
+{
+    comet_t    *comet;
+    int         portnum, mask;
+    u_int32_t   wdata, rdata;
+
+    wdata = COMET_MDIAG_LBOFF;      /* take port out of any loopback mode */
+
+    mask = 0;
+    for (portnum = 0; portnum < MUSYCC_NPORTS; portnum++)
+    {
+        comet = ci->port[portnum].cometbase;
+        pci_write_32 ((u_int32_t *) &comet->mdiag, wdata);
+        rdata = pci_read_32 ((u_int32_t *) &comet->mdiag) & COMET_MDIAG_LBMASK;
+        if (wdata == rdata)
+            mask |= 1 << portnum;
+    }
+    return mask;
+}
+
+
+/* nothing herein should generate interrupts */
+
+status_t    __init
+c4_init (ci_t * ci, u_char *func0, u_char *func1)
+{
+    mpi_t      *pi;
+    mch_t      *ch;
+    static u_int32_t count = 0;
+    int         portnum, j;
+
+    ci->state = C_INIT;
+    ci->brdno = count++;
+    ci->intlog.this_status_new = 0;
+    atomic_set (&ci->bh_pending, 0);
+
+    ci->reg = (struct musycc_globalr *) func0;
+    ci->eeprombase = (u_int32_t *) (func1 + EEPROM_OFFSET);
+    ci->cpldbase = (c4cpld_t *) ((u_int32_t *) (func1 + ISPLD_OFFSET));
+
+    /*** PORT POINT - the following is the first access of any type to the hardware ***/
+#ifdef CONFIG_SBE_PMCC4_NCOMM
+    /* NCOMM driver uses INTB interrupt to monitor CPLD register */
+    pci_write_32 ((u_int32_t *) &ci->reg->glcd, GCD_MAGIC);
+#else
+    /* standard driver POLLS for INTB via CPLD register */
+    pci_write_32 ((u_int32_t *) &ci->reg->glcd, GCD_MAGIC | MUSYCC_GCD_INTB_DISABLE);
+#endif
+
+    {
+        int         pmsk;
+
+        /* need comet addresses available for determination of hardware build */
+        for (portnum = 0; portnum < MUSYCC_NPORTS; portnum++)
+        {
+            pi = &ci->port[portnum];
+            pi->cometbase = (comet_t *) ((u_int32_t *) (func1 + COMET_OFFSET (portnum)));
+            pi->reg = (struct musycc_globalr *) ((u_char *) ci->reg + (portnum * 0x800));
+            pi->portnum = portnum;
+            pi->p.portnum = portnum;
+            pi->openchans = 0;
+#ifdef SBE_MAP_DEBUG
+            printk ("Comet-%d: addr = %p\n", portnum, pi->cometbase);
+#endif
+        }
+        pmsk = c4_get_portcfg (ci);
+        switch (pmsk)
+        {
+        case 0x1:
+            ci->max_port = 1;
+            break;
+        case 0x3:
+            ci->max_port = 2;
+            break;
+#if 0
+        case 0x7:                   /* not built, but could be... */
+            ci->max_port = 3;
+            break;
+#endif
+        case 0xf:
+            ci->max_port = 4;
+            break;
+        default:
+            ci->max_port = 0;
+            printk (KERN_WARNING "%s: illegal port configuration (%x)\n", ci->devname, pmsk);
+            return SBE_DRVR_FAIL;
+        }
+#ifdef SBE_MAP_DEBUG
+        printk (">> %s: c4_get_build - pmsk %x max_port %x\n", ci->devname, pmsk, ci->max_port);
+#endif
+    }
+
+    for (portnum = 0; portnum < ci->max_port; portnum++)
+    {
+        pi = &ci->port[portnum];
+        pi->up = ci;
+        pi->sr_last = 0xffffffff;
+        pi->p.port_mode = CFG_FRAME_SF; /* T1 B8ZS, the default */
+        pi->p.portP = (CFG_CLK_PORT_EXTERNAL | CFG_LBO_LH0);    /* T1 defaults */
+
+        OS_sem_init (&pi->sr_sem_busy, SEM_AVAILABLE);
+        OS_sem_init (&pi->sr_sem_wait, SEM_TAKEN);
+
+        for (j = 0; j < 32; j++)
+        {
+            pi->fifomap[j] = -1;
+            pi->tsm[j] = 0;         /* no assignments, all available */
+        }
+
+        /* allocate channel structures for this port */
+        for (j = 0; j < MUSYCC_NCHANS; j++)
+        {
+            ch = OS_kmalloc (sizeof (mch_t));
+            if (ch)
+            {
+                pi->chan[j] = ch;
+                ch->state = UNASSIGNED;
+                ch->up = pi;
+                ch->gchan = (-1);   /* channel assignment not yet known */
+                ch->channum = (-1); /* channel assignment not yet known */
+                ch->p.card = ci->brdno;
+                ch->p.port = portnum;
+                ch->p.channum = (-1);   /* channel assignment not yet known */
+                ch->p.mode_56k = 0; /* default is 64kbps mode */
+            } else
+            {
+                printk (KERN_WARNING "%s: failed mch_t malloc, port %d channel %d size %u.\n",
+                        THIS_MODULE->name, portnum, j, (unsigned int) sizeof (mch_t));
+                break;
+            }
+        }
+    }
+
+
+    {
+        /*
+         * Set LEDs through their paces to supply visual proof that LEDs are
+         * functional and not burnt out nor broken.
+         *
+         * YELLOW + GREEN -> OFF.
+         */
+
+        pci_write_32 ((u_int32_t *) &ci->cpldbase->leds,
+                      PMCC4_CPLD_LED_GREEN | PMCC4_CPLD_LED_YELLOW);
+        OS_uwait (750000, "leds");
+        pci_write_32 ((u_int32_t *) &ci->cpldbase->leds, PMCC4_CPLD_LED_OFF);
+    }
+
+    OS_init_watchdog (&ci->wd, (void (*) (void *)) c4_watchdog, ci, WATCHDOG_TIMEOUT);
+    return SBE_DRVR_SUCCESS;
+}
+
+
+/* better be fully setup to handle interrupts when you call this */
+
+status_t    __init
+c4_init2 (ci_t * ci)
+{
+    status_t    ret;
+
+    /* PORT POINT: this routine generates first interrupt */
+    if ((ret = musycc_init (ci)) != SBE_DRVR_SUCCESS)
+        return ret;
+
+#if 0
+    ci->p.framing_type = FRAMING_CBP;
+    ci->p.h110enable = 1;
+#if 0
+    ci->p.hypersize = 0;
+#else
+    hyperdummy = 0;
+#endif
+    ci->p.clock = 0;                /* Use internal clocking until set to
+                                     * external */
+    c4_card_set_params (ci, &ci->p);
+#endif
+    OS_start_watchdog (&ci->wd);
+    return SBE_DRVR_SUCCESS;
+}
+
+
+/* This function sets the loopback mode (or clears it, as the case may be). */
+
+int
+c4_loop_port (ci_t * ci, int portnum, u_int8_t cmd)
+{
+    comet_t    *comet;
+    volatile u_int32_t loopValue;
+
+    comet = ci->port[portnum].cometbase;
+    loopValue = pci_read_32 ((u_int32_t *) &comet->mdiag) & COMET_MDIAG_LBMASK;
+
+    if (cmd & COMET_LBCMD_READ)
+        return loopValue;           /* return the read value */
+
+    if (loopValue != cmd)
+    {
+        switch (cmd)
+        {
+        case COMET_MDIAG_LINELB:
+            /* set(SF)loopback down (turn off) code length to 6 bits */
+            pci_write_32 ((u_int32_t *) &comet->ibcd_cfg, 0x05);
+            break;
+        case COMET_MDIAG_LBOFF:
+            /* set (SF) loopback up (turn on) code length to 5 bits */
+            pci_write_32 ((u_int32_t *) &comet->ibcd_cfg, 0x00);
+            break;
+        }
+
+        pci_write_32 ((u_int32_t *) &comet->mdiag, cmd);
+        if (log_level >= LOG_WARN)
+            printk ("%s: loopback mode changed to %2x from %2x on Port %d\n",
+                    ci->devname, cmd, loopValue, portnum);
+        loopValue = pci_read_32 ((u_int32_t *) &comet->mdiag) & COMET_MDIAG_LBMASK;
+        if (loopValue != cmd)
+        {
+            if (log_level >= LOG_ERROR)
+                printk ("%s: write to loop register failed, unknown state for Port %d\n",
+                        ci->devname, portnum);
+        }
+    } else
+    {
+        if (log_level >= LOG_WARN)
+            printk ("%s: loopback already in that mode (%2x)\n", ci->devname, loopValue);
+    }
+    return 0;
+}
+
+
+/* c4_frame_rw: read or write the comet register specified
+ * (modifies use of port_param to non-standard use of struct)
+ * Specifically:
+ *   pp.portnum     (one guess)
+ *   pp.port_mode   offset of register
+ *   pp.portP       write (or not, i.e. read)
+ *   pp.portStatus  write value
+ * BTW:
+ *   pp.portStatus  also used to return read value
+ *   pp.portP       also used during write, to return old reg value
+ */
+
+status_t
+c4_frame_rw (ci_t * ci, struct sbecom_port_param * pp)
+{
+    comet_t    *comet;
+    volatile u_int32_t data;
+
+    if (pp->portnum >= ci->max_port)/* sanity check */
+        return ENXIO;
+
+    comet = ci->port[pp->portnum].cometbase;
+    data = pci_read_32 ((u_int32_t *) comet + pp->port_mode) & 0xff;
+
+    if (pp->portP)
+    {                               /* control says this is a register
+                                     * _write_ */
+        if (pp->portStatus == data)
+            printk ("%s: Port %d already that value!  Writing again anyhow.\n",
+                    ci->devname, pp->portnum);
+        pp->portP = (u_int8_t) data;
+        pci_write_32 ((u_int32_t *) comet + pp->port_mode,
+                      pp->portStatus);
+        data = pci_read_32 ((u_int32_t *) comet + pp->port_mode) & 0xff;
+    }
+    pp->portStatus = (u_int8_t) data;
+    return 0;
+}
+
+
+/* c4_pld_rw: read or write the pld register specified
+ * (modifies use of port_param to non-standard use of struct)
+ * Specifically:
+ *   pp.port_mode   offset of register
+ *   pp.portP       write (or not, i.e. read)
+ *   pp.portStatus  write value
+ * BTW:
+ *   pp.portStatus  also used to return read value
+ *   pp.portP       also used during write, to return old reg value
+ */
+
+status_t
+c4_pld_rw (ci_t * ci, struct sbecom_port_param * pp)
+{
+    volatile u_int32_t *regaddr;
+    volatile u_int32_t data;
+    int         regnum = pp->port_mode;
+
+    regaddr = (u_int32_t *) ci->cpldbase + regnum;
+    data = pci_read_32 ((u_int32_t *) regaddr) & 0xff;
+
+    if (pp->portP)
+    {                               /* control says this is a register
+                                     * _write_ */
+        pp->portP = (u_int8_t) data;
+        pci_write_32 ((u_int32_t *) regaddr, pp->portStatus);
+        data = pci_read_32 ((u_int32_t *) regaddr) & 0xff;
+    }
+    pp->portStatus = (u_int8_t) data;
+    return 0;
+}
+
+/* c4_musycc_rw: read or write the musycc register specified
+ * (modifies use of port_param to non-standard use of struct)
+ * Specifically:
+ *    mcp.RWportnum   port number and write indication bit (0x80)
+ *    mcp.offset      offset of register
+ *    mcp.value       write value going in and read value returning
+ */
+
+/* PORT POINT: TX Subchannel Map registers are write-only
+ * areas within the MUSYCC and always return FF */
+/* PORT POINT: regram and reg structures are minorly different and <offset> ioctl
+ * settings are aligned with the <reg> struct musycc_globalr{} usage.
+ * Also, regram is separately allocated shared memory, allocated for each port.
+ * PORT POINT: access offsets of 0x6000 for Msg Cfg Desc Tbl are for 4-port MUSYCC
+ * only.  (An 8-port MUSYCC has 0x16000 offsets for accessing its upper 4 tables.)
+ */
+
+status_t
+c4_musycc_rw (ci_t * ci, struct c4_musycc_param * mcp)
+{
+    mpi_t      *pi;
+    volatile u_int32_t *dph;    /* hardware implemented register */
+    u_int32_t  *dpr = 0;        /* RAM image of registers for group command
+                                 * usage */
+    int         offset = mcp->offset % 0x800;   /* group relative address
+                                                 * offset, mcp->portnum is
+                                                 * not used */
+    int         portnum, ramread = 0;
+    volatile u_int32_t data;
+
+    /*
+     * Sanity check hardware accessibility.  The 0x6000 portion handles port
+     * numbers associated with Msg Descr Tbl decoding.
+     */
+    portnum = (mcp->offset % 0x6000) / 0x800;
+    if (portnum >= ci->max_port)
+        return ENXIO;
+    pi = &ci->port[portnum];
+    if (mcp->offset >= 0x6000)
+        offset += 0x6000;           /* put back in MsgCfgDesc address offset */
+    dph = (u_int32_t *) ((u_long) pi->reg + offset);
+
+    /* read of TX are from RAM image, since hardware returns FF */
+    dpr = (u_int32_t *) ((u_long) pi->regram + offset);
+    if (mcp->offset < 0x6000)       /* non MsgDesc Tbl accesses might require
+                                     * RAM access */
+    {
+        if (offset >= 0x200 && offset < 0x380)
+            ramread = 1;
+        if (offset >= 0x10 && offset < 0x200)
+            ramread = 1;
+    }
+    /* read register from RAM or hardware, depending... */
+    if (ramread)
+    {
+        data = *dpr;
+        //printk ("c4_musycc_rw: RAM addr %p  read data %x (portno %x offset %x RAM ramread %x)\n", dpr, data, portnum, offset, ramread); /* RLD DEBUG */
+    } else
+    {
+        data = pci_read_32 ((u_int32_t *) dph);
+        //printk ("c4_musycc_rw: REG addr %p  read data %x (portno %x offset %x RAM ramread %x)\n", dph, data, portnum, offset, ramread); /* RLD DEBUG */
+    }
+
+
+    if (mcp->RWportnum & 0x80)
+    {                               /* control says this is a register
+                                     * _write_ */
+        if (mcp->value == data)
+            printk ("%s: musycc grp%d already that value! writing again anyhow.\n",
+                    ci->devname, (mcp->RWportnum & 0x7));
+        /* write register RAM */
+        if (ramread)
+            *dpr = mcp->value;
+        /* write hardware register */
+        pci_write_32 ((u_int32_t *) dph, mcp->value);
+    }
+    mcp->value = data;              /* return the read value (or the 'old
+                                     * value', if is write) */
+    return 0;
+}
+
+status_t
+c4_get_port (ci_t * ci, int portnum)
+{
+    if (portnum >= ci->max_port)    /* sanity check */
+        return ENXIO;
+
+    SD_SEM_TAKE (&ci->sem_wdbusy, "_wd_");      /* only 1 thru here, per
+                                                 * board */
+    checkPorts (ci);
+    ci->port[portnum].p.portStatus = (u_int8_t) ci->alarmed[portnum];
+    ci->alarmed[portnum] &= 0xdf;
+    SD_SEM_GIVE (&ci->sem_wdbusy);  /* release per-board hold */
+    return 0;
+}
+
+status_t
+c4_set_port (ci_t * ci, int portnum)
+{
+    mpi_t      *pi;
+    struct sbecom_port_param *pp;
+    int         e1mode;
+    u_int8_t    clck;
+    int         i;
+
+    if (portnum >= ci->max_port)    /* sanity check */
+        return ENXIO;
+
+    pi = &ci->port[portnum];
+    pp = &ci->port[portnum].p;
+    e1mode = IS_FRAME_ANY_E1 (pp->port_mode);
+    if (log_level >= LOG_MONITOR2)
+    {
+        printk ("%s: c4_set_port[%d]:  entered, e1mode = %x, openchans %d.\n",
+                ci->devname,
+                portnum, e1mode, pi->openchans);
+    }
+    if (pi->openchans)
+        return EBUSY;               /* group needs initialization only for
+                                     * first channel of a group */
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
+    {
+        status_t    ret;
+
+        if ((ret = c4_wq_port_init (pi)))       /* create/init
+                                                 * workqueue_struct */
+            return (ret);
+    }
+#endif
+
+    init_comet (ci, pi->cometbase, pp->port_mode, 1 /* clockmaster == true */ , pp->portP);
+    clck = pci_read_32 ((u_int32_t *) &ci->cpldbase->mclk) & PMCC4_CPLD_MCLK_MASK;
+    if (e1mode)
+        clck |= 1 << portnum;
+    else
+        clck &= 0xf ^ (1 << portnum);
+
+    pci_write_32 ((u_int32_t *) &ci->cpldbase->mclk, clck);
+    pci_write_32 ((u_int32_t *) &ci->cpldbase->mcsr, PMCC4_CPLD_MCSR_IND);
+    pci_write_32 ((u_int32_t *) &pi->reg->gbp, OS_vtophys (pi->regram));
+
+    /*********************************************************************/
+    /* ERRATA: If transparent mode is used, do not set OOFMP_DISABLE bit */
+    /*********************************************************************/
+
+    pi->regram->grcd =
+        __constant_cpu_to_le32 (MUSYCC_GRCD_RX_ENABLE |
+                                MUSYCC_GRCD_TX_ENABLE |
+                                MUSYCC_GRCD_OOFMP_DISABLE |
+                                MUSYCC_GRCD_SF_ALIGN |  /* per MUSYCC ERRATA,
+                                                         * for T1 * fix */
+                                MUSYCC_GRCD_COFAIRQ_DISABLE |
+                                MUSYCC_GRCD_MC_ENABLE |
+                       (MUSYCC_GRCD_POLLTH_32 << MUSYCC_GRCD_POLLTH_SHIFT));
+
+    pi->regram->pcd =
+        __constant_cpu_to_le32 ((e1mode ? 1 : 0) |
+                                MUSYCC_PCD_TXSYNC_RISING |
+                                MUSYCC_PCD_RXSYNC_RISING |
+                                MUSYCC_PCD_RXDATA_RISING);
+
+    /* Message length descriptor */
+    pi->regram->mld = __constant_cpu_to_le32 (max_mru | (max_mru << 16));
+
+    /* tsm algorithm */
+    for (i = 0; i < 32; i++)
+    {
+
+        /*** ASSIGNMENT NOTES:                             ***/
+        /*** Group's channel  ZERO  unavailable if E1.     ***/
+        /*** Group's channel  16    unavailable if E1 CAS. ***/
+        /*** Group's channels 24-31 unavailable if T1.     ***/
+
+        if (((i == 0) && e1mode) ||
+            ((i == 16) && ((pp->port_mode == CFG_FRAME_E1CRC_CAS) || (pp->port_mode == CFG_FRAME_E1CRC_CAS_AMI)))
+            || ((i > 23) && (!e1mode)))
+        {
+            pi->tsm[i] = 0xff;      /* make tslot unavailable for this mode */
+        } else
+        {
+            pi->tsm[i] = 0x00;      /* make tslot available for assignment */
+        }
+    }
+    for (i = 0; i < MUSYCC_NCHANS; i++)
+    {
+        pi->regram->ttsm[i] = 0;
+        pi->regram->rtsm[i] = 0;
+    }
+    FLUSH_MEM_WRITE ();
+    musycc_serv_req (pi, SR_GROUP_INIT | SR_RX_DIRECTION);
+    musycc_serv_req (pi, SR_GROUP_INIT | SR_TX_DIRECTION);
+
+    musycc_init_mdt (pi);
+
+    pi->group_is_set = 1;
+    pi->p = *pp;
+    return 0;
+}
+
+
+unsigned int max_int = 0;
+
+status_t
+c4_new_chan (ci_t * ci, int portnum, int channum, void *user)
+{
+    mpi_t      *pi;
+    mch_t      *ch;
+    int         gchan;
+
+    if (c4_find_chan (channum))     /* a new channel shouldn't already exist */
+        return EEXIST;
+
+    if (portnum >= ci->max_port)    /* sanity check */
+        return ENXIO;
+
+    pi = &(ci->port[portnum]);
+    /* find any available channel within this port */
+    for (gchan = 0; gchan < MUSYCC_NCHANS; gchan++)
+    {
+        ch = pi->chan[gchan];
+        if (ch && ch->state == UNASSIGNED)      /* no assignment is good! */
+            break;
+    }
+    if (gchan == MUSYCC_NCHANS)     /* exhausted table, all were assigned */
+        return ENFILE;
+
+    ch->up = pi;
+
+    /* NOTE: mch_t already cleared during OS_kmalloc() */
+    ch->state = DOWN;
+    ch->user = user;
+    ch->gchan = gchan;
+    ch->channum = channum;          /* mark our channel assignment */
+    ch->p.channum = channum;
+#if 1
+    ch->p.card = ci->brdno;
+    ch->p.port = portnum;
+#endif
+    ch->p.chan_mode = CFG_CH_PROTO_HDLC_FCS16;
+    ch->p.idlecode = CFG_CH_FLAG_7E;
+    ch->p.pad_fill_count = 2;
+    spin_lock_init (&ch->ch_rxlock);
+    spin_lock_init (&ch->ch_txlock);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
+    {
+        status_t    ret;
+
+        if ((ret = c4_wk_chan_init (pi, ch)))
+            return ret;
+    }
+#endif
+
+    /* save off interface assignments which bound a board */
+    if (ci->first_if == 0)          /* first channel registered is assumed to
+                                     * be the lowest channel */
+    {
+        ci->first_if = ci->last_if = user;
+        ci->first_channum = ci->last_channum = channum;
+    } else
+    {
+        ci->last_if = user;
+        if (ci->last_channum < channum) /* higher number channel found */
+            ci->last_channum = channum;
+    }
+    return 0;
+}
+
+status_t
+c4_del_chan (int channum)
+{
+    mch_t      *ch;
+
+    if (!(ch = c4_find_chan (channum)))
+        return ENOENT;
+    if (ch->state == UP)
+        musycc_chan_down ((ci_t *) 0, channum);
+    ch->state = UNASSIGNED;
+    ch->gchan = (-1);
+    ch->channum = (-1);
+    ch->p.channum = (-1);
+    return 0;
+}
+
+status_t
+c4_del_chan_stats (int channum)
+{
+    mch_t      *ch;
+
+    if (!(ch = c4_find_chan (channum)))
+        return ENOENT;
+
+    memset (&ch->s, 0, sizeof (struct sbecom_chan_stats));
+    return 0;
+}
+
+
+status_t
+c4_set_chan (int channum, struct sbecom_chan_param * p)
+{
+    mch_t      *ch;
+    int         i, x = 0;
+
+    if (!(ch = c4_find_chan (channum)))
+        return ENOENT;
+
+#if 1
+    if (ch->p.card != p->card ||
+        ch->p.port != p->port ||
+        ch->p.channum != p->channum)
+        return EINVAL;
+#endif
+
+    if (!(ch->up->group_is_set))
+    {
+        return EIO;                 /* out of order, SET_PORT command
+                                     * required prior to first group's
+                                     * SET_CHAN command */
+    }
+    /*
+     * Check for change of parameter settings in order to invoke closing of
+     * channel prior to hardware poking.
+     */
+
+    if (ch->p.status != p->status || ch->p.chan_mode != p->chan_mode ||
+        ch->p.data_inv != p->data_inv || ch->p.intr_mask != p->intr_mask ||
+        ch->txd_free < ch->txd_num) /* to clear out queued messages */
+        x = 1;                      /* we have a change requested */
+    for (i = 0; i < 32; i++)        /* check for timeslot mapping changes */
+        if (ch->p.bitmask[i] != p->bitmask[i])
+            x = 1;                  /* we have a change requested */
+    ch->p = *p;
+    if (x && (ch->state == UP))     /* if change request and channel is
+                                     * open... */
+    {
+        status_t    ret;
+
+        if ((ret = musycc_chan_down ((ci_t *) 0, channum)))
+            return ret;
+        if ((ret = c4_chan_up (ch->up->up, channum)))
+            return ret;
+        sd_enable_xmit (ch->user);  /* re-enable to catch flow controlled
+                                     * channel */
+    }
+    return 0;
+}
+
+
+status_t
+c4_get_chan (int channum, struct sbecom_chan_param * p)
+{
+    mch_t      *ch;
+
+    if (!(ch = c4_find_chan (channum)))
+        return ENOENT;
+    *p = ch->p;
+    return 0;
+}
+
+status_t
+c4_get_chan_stats (int channum, struct sbecom_chan_stats * p)
+{
+    mch_t      *ch;
+
+    if (!(ch = c4_find_chan (channum)))
+        return ENOENT;
+    *p = ch->s;
+    p->tx_pending = atomic_read (&ch->tx_pending);
+    return 0;
+}
+
+STATIC int
+c4_fifo_alloc (mpi_t * pi, int chan, int *len)
+{
+    int         i, l = 0, start = 0, max = 0, maxstart = 0;
+
+    for (i = 0; i < 32; i++)
+    {
+        if (pi->fifomap[i] != -1)
+        {
+            l = 0;
+            start = i + 1;
+            continue;
+        }
+        ++l;
+        if (l > max)
+        {
+            max = l;
+            maxstart = start;
+        }
+        if (max == *len)
+            break;
+    }
+    if (max != *len)
+    {
+        if (log_level >= LOG_WARN)
+            printk (
+                  "%s: wanted to allocate %d fifo space, but got only %d\n",
+                    pi->up->devname, *len, max);
+        *len = max;
+    }
+    if (log_level >= LOG_DEBUG)
+        printk ("%s: allocated %d fifo at %d for channel %d/%d\n",
+                pi->up->devname, max, start, chan, pi->p.portnum);
+    for (i = maxstart; i < (maxstart + max); i++)
+        pi->fifomap[i] = chan;
+    return start;
+}
+
+void
+c4_fifo_free (mpi_t * pi, int chan)
+{
+    int         i;
+
+    if (log_level >= LOG_DEBUG)
+        printk ("%s: deallocated fifo for channel %d/%d\n",
+                pi->up->devname, chan, pi->p.portnum);
+    for (i = 0; i < 32; i++)
+        if (pi->fifomap[i] == chan)
+            pi->fifomap[i] = -1;
+}
+
+
+status_t
+c4_chan_up (ci_t * ci, int channum)
+{
+    mpi_t      *pi;
+    mch_t      *ch;
+    struct mbuf *m;
+    struct mdesc *md;
+    int         nts, nbuf, txnum, rxnum;
+    int         addr, i, j, gchan;
+    u_int32_t   tmp;            /* for optimizing conversion across BE
+                                 * platform */
+
+    if (!(ch = c4_find_chan (channum)))
+        return ENOENT;
+    if (ch->state == UP)
+    {
+        if (log_level >= LOG_MONITOR)
+            printk ("%s: channel already UP, graceful early exit\n", ci->devname);
+        return 0;
+    }
+    pi = ch->up;
+    gchan = ch->gchan;
+    /* find nts ('number of timeslots') */
+    nts = 0;
+    for (i = 0; i < 32; i++)
+    {
+        if (ch->p.bitmask[i] & pi->tsm[i])
+        {
+            if (1 || log_level >= LOG_WARN)
+            {
+                printk ("%s: c4_chan_up[%d] EINVAL (attempt to cfg in-use or unavailable TimeSlot[%d])\n",
+                        ci->devname, channum, i);
+                printk ("+ ask4 %x, currently %x\n", ch->p.bitmask[i], pi->tsm[i]);
+            }
+            return EINVAL;
+        }
+        for (j = 0; j < 8; j++)
+            if (ch->p.bitmask[i] & (1 << j))
+                nts++;
+    }
+
+    nbuf = nts / 8 ? nts / 8 : 1;
+    if (!nbuf)
+    {
+        /* if( log_level >= LOG_WARN)  */
+        printk ("%s: c4_chan_up[%d] ENOBUFS (no TimeSlots assigned)\n", ci->devname, channum);
+        return ENOBUFS;             /* this should not happen */
+    }
+    addr = c4_fifo_alloc (pi, gchan, &nbuf);
+    ch->state = UP;
+
+    /* Setup the Time Slot Map */
+    musycc_update_timeslots (pi);
+
+    /* ch->tx_limit = nts; */
+    ch->s.tx_pending = 0;
+
+    /* Set Channel Configuration Descriptors */
+    {
+        u_int32_t   ccd;
+
+        ccd = musycc_chan_proto (ch->p.chan_mode) << MUSYCC_CCD_PROTO_SHIFT;
+        if ((ch->p.chan_mode == CFG_CH_PROTO_ISLP_MODE) ||
+            (ch->p.chan_mode == CFG_CH_PROTO_TRANS))
+        {
+            ccd |= MUSYCC_CCD_FCS_XFER; /* Non FSC Mode */
+        }
+        ccd |= 2 << MUSYCC_CCD_MAX_LENGTH;      /* Select second MTU */
+        ccd |= ch->p.intr_mask;
+        ccd |= addr << MUSYCC_CCD_BUFFER_LOC;
+        if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
+            ccd |= (nbuf) << MUSYCC_CCD_BUFFER_LENGTH;
+        else
+            ccd |= (nbuf - 1) << MUSYCC_CCD_BUFFER_LENGTH;
+
+        if (ch->p.data_inv & CFG_CH_DINV_TX)
+            ccd |= MUSYCC_CCD_INVERT_DATA;      /* Invert data */
+        pi->regram->tcct[gchan] = cpu_to_le32 (ccd);
+
+        if (ch->p.data_inv & CFG_CH_DINV_RX)
+            ccd |= MUSYCC_CCD_INVERT_DATA;      /* Invert data */
+        else
+            ccd &= ~MUSYCC_CCD_INVERT_DATA;     /* take away data inversion */
+        pi->regram->rcct[gchan] = cpu_to_le32 (ccd);
+        FLUSH_MEM_WRITE ();
+    }
+
+    /* Reread the Channel Configuration Descriptor for this channel */
+    musycc_serv_req (pi, SR_CHANNEL_CONFIG | SR_RX_DIRECTION | gchan);
+    musycc_serv_req (pi, SR_CHANNEL_CONFIG | SR_TX_DIRECTION | gchan);
+
+    /*
+     * Figure out how many buffers we want.  If the customer has changed from
+     * the defaults, then use the changed values.  Otherwise, use Transparent
+     * mode's specific minimum default settings.
+     */
+    if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
+    {
+        if (max_rxdesc_used == max_rxdesc_default)      /* use default setting */
+            max_rxdesc_used = MUSYCC_RXDESC_TRANS;
+        if (max_txdesc_used == max_txdesc_default)      /* use default setting */
+            max_txdesc_used = MUSYCC_TXDESC_TRANS;
+    }
+    /*
+     * Increase counts when hyperchanneling, since this implies an increase
+     * in throughput per channel
+     */
+    rxnum = max_rxdesc_used + (nts / 4);
+    txnum = max_txdesc_used + (nts / 4);
+
+#if 0
+    /* DEBUG INFO */
+    if (log_level >= LOG_MONITOR)
+        printk ("%s: mode %x rxnum %d (rxused %d def %d) txnum %d (txused %d def %d)\n",
+                ci->devname, ch->p.chan_mode,
+                rxnum, max_rxdesc_used, max_rxdesc_default,
+                txnum, max_txdesc_used, max_txdesc_default);
+#endif
+
+    ch->rxd_num = rxnum;
+    ch->txd_num = txnum;
+    ch->rxix_irq_srv = 0;
+
+    ch->mdr = OS_kmalloc (sizeof (struct mdesc) * rxnum);
+    ch->mdt = OS_kmalloc (sizeof (struct mdesc) * txnum);
+    if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
+        tmp = __constant_cpu_to_le32 (max_mru | EOBIRQ_ENABLE);
+    else
+        tmp = __constant_cpu_to_le32 (max_mru);
+
+    for (i = 0, md = ch->mdr; i < rxnum; i++, md++)
+    {
+        if (i == (rxnum - 1))
+        {
+            md->snext = &ch->mdr[0];/* wrapness */
+        } else
+        {
+            md->snext = &ch->mdr[i + 1];
+        }
+        md->next = cpu_to_le32 (OS_vtophys (md->snext));
+
+        if (!(m = OS_mem_token_alloc (max_mru)))
+        {
+            if (log_level >= LOG_MONITOR)
+                printk ("%s: c4_chan_up[%d] - token alloc failure, size = %d.\n", ci->devname, channum, max_mru);
+            goto errfree;
+        }
+        md->mem_token = m;
+        md->data = cpu_to_le32 (OS_vtophys (OS_mem_token_data (m)));
+        md->status = tmp | MUSYCC_RX_OWNED;     /* MUSYCC owns RX descriptor **
+                                                 * CODING NOTE:
+                                                 * MUSYCC_RX_OWNED = 0 so no
+                                                 * need to byteSwap */
+    }
+
+    for (i = 0, md = ch->mdt; i < txnum; i++, md++)
+    {
+        md->status = HOST_TX_OWNED; /* Host owns TX descriptor ** CODING
+                                     * NOTE: HOST_TX_OWNED = 0 so no need to
+                                     * byteSwap */
+        md->mem_token = 0;
+        md->data = 0;
+        if (i == (txnum - 1))
+        {
+            md->snext = &ch->mdt[0];/* wrapness */
+        } else
+        {
+            md->snext = &ch->mdt[i + 1];
+        }
+        md->next = cpu_to_le32 (OS_vtophys (md->snext));
+    }
+    ch->txd_irq_srv = ch->txd_usr_add = &ch->mdt[0];
+    ch->txd_free = txnum;
+    ch->tx_full = 0;
+    ch->txd_required = 0;
+
+    /* Configure it into the chip */
+    tmp = cpu_to_le32 (OS_vtophys (&ch->mdt[0]));
+    pi->regram->thp[gchan] = tmp;
+    pi->regram->tmp[gchan] = tmp;
+
+    tmp = cpu_to_le32 (OS_vtophys (&ch->mdr[0]));
+    pi->regram->rhp[gchan] = tmp;
+    pi->regram->rmp[gchan] = tmp;
+
+    /* Activate the Channel */
+    FLUSH_MEM_WRITE ();
+    if (ch->p.status & RX_ENABLED)
+    {
+#ifdef RLD_TRANS_DEBUG
+        printk ("++ c4_chan_up() CHAN RX ACTIVATE: chan %d\n", ch->channum);
+#endif
+        ch->ch_start_rx = 0;        /* we are restarting RX... */
+        musycc_serv_req (pi, SR_CHANNEL_ACTIVATE | SR_RX_DIRECTION | gchan);
+    }
+    if (ch->p.status & TX_ENABLED)
+    {
+#ifdef RLD_TRANS_DEBUG
+        printk ("++ c4_chan_up() CHAN TX ACTIVATE: chan %d <delayed>\n", ch->channum);
+#endif
+        ch->ch_start_tx = CH_START_TX_1ST;      /* we are delaying start
+                                                 * until receipt from user of
+                                                 * first packet to transmit. */
+    }
+    ch->status = ch->p.status;
+    pi->openchans++;
+    return 0;
+
+errfree:
+    while (i > 0)
+    {
+        /* Don't leak all the previously allocated mbufs in this loop */
+        i--;
+        OS_mem_token_free (ch->mdr[i].mem_token);
+    }
+    OS_kfree (ch->mdt);
+    ch->mdt = 0;
+    ch->txd_num = 0;
+    OS_kfree (ch->mdr);
+    ch->mdr = 0;
+    ch->rxd_num = 0;
+    ch->state = DOWN;
+    return ENOBUFS;
+}
+
+/* stop the hardware from servicing & interrupting */
+
+void
+c4_stopwd (ci_t * ci)
+{
+    OS_stop_watchdog (&ci->wd);
+    SD_SEM_TAKE (&ci->sem_wdbusy, "_stop_");    /* ensure WD not running */
+    SD_SEM_GIVE (&ci->sem_wdbusy);
+}
+
+
+void
+sbecom_get_brdinfo (ci_t * ci, struct sbe_brd_info * bip, u_int8_t *bsn)
+{
+    char       *np;
+    u_int32_t   sn = 0;
+    int         i;
+
+    bip->brdno = ci->brdno;         /* our board number */
+    bip->brd_id = ci->brd_id;
+    bip->brd_hdw_id = ci->hdw_bid;
+    bip->brd_chan_cnt = MUSYCC_NCHANS * ci->max_port;   /* number of channels
+                                                         * being used */
+    bip->brd_port_cnt = ci->max_port;   /* number of ports being used */
+    bip->brd_pci_speed = BINFO_PCI_SPEED_unk;   /* PCI speed not yet
+                                                 * determinable */
+
+    if (ci->first_if)
+    {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+        np = (char *) hdlc_to_name (ci->first_if);
+#else
+        {
+            struct net_device *dev;
+
+            dev = (struct net_device *) ci->first_if;
+            np = (char *) dev->name;
+        }
+#endif
+        strncpy (bip->first_iname, np, CHNM_STRLEN - 1);
+    } else
+        strcpy (bip->first_iname, "<NULL>");
+    if (ci->last_if)
+    {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+        np = (char *) hdlc_to_name (ci->last_if);
+#else
+        {
+            struct net_device *dev;
+
+            dev = (struct net_device *) ci->last_if;
+            np = (char *) dev->name;
+        }
+#endif
+        strncpy (bip->last_iname, np, CHNM_STRLEN - 1);
+    } else
+        strcpy (bip->last_iname, "<NULL>");
+
+    if (bsn)
+    {
+        for (i = 0; i < 3; i++)
+        {
+            bip->brd_mac_addr[i] = *bsn++;
+        }
+        for (; i < 6; i++)
+        {
+            bip->brd_mac_addr[i] = *bsn;
+            sn = (sn << 8) | *bsn++;
+        }
+    } else
+    {
+        for (i = 0; i < 6; i++)
+            bip->brd_mac_addr[i] = 0;
+    }
+    bip->brd_sn = sn;
+}
+
+
+status_t
+c4_get_iidinfo (ci_t * ci, struct sbe_iid_info * iip)
+{
+    struct net_device *dev;
+    char       *np;
+
+    if (!(dev = getuserbychan (iip->channum)))
+        return ENOENT;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+    np = (char *) hdlc_to_name (dev_to_hdlc (dev));
+#else
+    np = dev->name;
+#endif
+    strncpy (iip->iname, np, CHNM_STRLEN - 1);
+    return 0;
+}
+
+
+#ifdef CONFIG_SBE_PMCC4_NCOMM
+void        (*nciInterrupt[MAX_BOARDS][4]) (void);
+extern void wanpmcC4T1E1_hookInterrupt (int cardID, int deviceID, void *handler);
+
+void
+wanpmcC4T1E1_hookInterrupt (int cardID, int deviceID, void *handler)
+{
+    if (cardID < MAX_BOARDS)    /* sanity check */
+        nciInterrupt[cardID][deviceID] = handler;
+}
+
+irqreturn_t
+c4_ebus_intr_th_handler (void *devp)
+{
+    ci_t       *ci = (ci_t *) devp;
+    volatile u_int32_t ists;
+    int         handled = 0;
+    int         brdno;
+
+    /* which COMET caused the interrupt */
+    brdno = ci->brdno;
+    ists = pci_read_32 ((u_int32_t *) &ci->cpldbase->intr);
+    if (ists & PMCC4_CPLD_INTR_CMT_1)
+    {
+        handled = 0x1;
+        if (nciInterrupt[brdno][0] != NULL)
+            (*nciInterrupt[brdno][0]) ();
+    }
+    if (ists & PMCC4_CPLD_INTR_CMT_2)
+    {
+        handled |= 0x2;
+        if (nciInterrupt[brdno][1] != NULL)
+            (*nciInterrupt[brdno][1]) ();
+    }
+    if (ists & PMCC4_CPLD_INTR_CMT_3)
+    {
+        handled |= 0x4;
+        if (nciInterrupt[brdno][2] != NULL)
+            (*nciInterrupt[brdno][2]) ();
+    }
+    if (ists & PMCC4_CPLD_INTR_CMT_4)
+    {
+        handled |= 0x8;
+        if (nciInterrupt[brdno][3] != NULL)
+            (*nciInterrupt[brdno][3]) ();
+    }
+#if 0
+    /*** Test code just de-implements the asserted interrupt.  Alternate
+    vendor will supply COMET interrupt handling code herein or such.
+    ***/
+    pci_write_32 ((u_int32_t *) &ci->reg->glcd, GCD_MAGIC | MUSYCC_GCD_INTB_DISABLE);
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,20)
+    return;
+#else
+    return IRQ_RETVAL (handled);
+#endif
+}
+
+
+unsigned long
+wanpmcC4T1E1_getBaseAddress (int cardID, int deviceID)
+{
+    ci_t       *ci;
+    unsigned long base = 0;
+
+    ci = c4_list;
+    while (ci)
+    {
+        if (ci->brdno == cardID)    /* found valid device */
+        {
+            if (deviceID < ci->max_port)        /* comet is supported */
+                base = ((unsigned long) ci->port[deviceID].cometbase);
+            break;
+        }
+        ci = ci->next;              /* next board, if any */
+    }
+    return (base);
+}
+
+#endif                          /*** CONFIG_SBE_PMCC4_NCOMM ***/
+
+
+/***  End-of-File  ***/
diff --git a/drivers/staging/cxt1e1/pmcc4_ioctls.h b/drivers/staging/cxt1e1/pmcc4_ioctls.h
new file mode 100644 (file)
index 0000000..6b8d656
--- /dev/null
@@ -0,0 +1,81 @@
+/* RCSid: $Header: /home/rickd/projects/pmcc4/include/pmcc4_ioctls.h,v 2.0 2005/09/28 00:10:09 rickd PMCC4_3_1B $
+ */
+
+#ifndef _INC_PMCC4_IOCTLS_H_
+#define _INC_PMCC4_IOCTLS_H_
+
+/*-----------------------------------------------------------------------------
+ * pmcc4_ioctls.h -
+ *
+ * Copyright (C) 2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@sbei.com
+ * SBE, Inc.  San Ramon, California  U.S.A.
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 2.0 $
+ * Last changed on $Date: 2005/09/28 00:10:09 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: pmcc4_ioctls.h,v $
+ * Revision 2.0  2005/09/28 00:10:09  rickd
+ * Add GNU license info. Switch Ioctls to sbe_ioc.h usage.
+ *
+ * Revision 1.2  2005/04/28 23:43:03  rickd
+ * Add RCS tracking heading.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#include "sbew_ioc.h"
+
+enum
+{
+    // C4_GET_PORT = 0,
+    // C4_SET_PORT,
+    // C4_GET_CHAN,
+    // C4_SET_CHAN,
+    C4_DEL_CHAN = 0,
+    // C4_CREATE_CHAN,
+    // C4_GET_CHAN_STATS,
+    // C4_RESET,
+    // C4_DEBUG,
+    C4_RESET_STATS,
+    C4_LOOP_PORT,
+    C4_RW_FRMR,
+    C4_RW_MSYC,
+    C4_RW_PLD
+};
+
+#define C4_GET_PORT          SBE_IOC_PORT_GET
+#define C4_SET_PORT          SBE_IOC_PORT_SET
+#define C4_GET_CHAN          SBE_IOC_CHAN_GET
+#define C4_SET_CHAN          SBE_IOC_CHAN_SET
+// #define C4_DEL_CHAN          XXX
+#define C4_CREATE_CHAN       SBE_IOC_CHAN_NEW
+#define C4_GET_CHAN_STATS    SBE_IOC_CHAN_GET_STAT
+#define C4_RESET             SBE_IOC_RESET_DEV
+#define C4_DEBUG             SBE_IOC_LOGLEVEL
+// #define C4_RESET_STATS       XXX
+// #define C4_LOOP_PORT         XXX
+// #define C4_RW_FRMR           XXX
+// #define C4_RW_MSYC           XXX
+// #define C4_RW_PLD            XXX
+
+struct c4_chan_stats_wrap
+{
+    int         channum;
+    struct sbecom_chan_stats stats;
+};
+
+#endif   /* _INC_PMCC4_IOCTLS_H_ */
diff --git a/drivers/staging/cxt1e1/pmcc4_private.h b/drivers/staging/cxt1e1/pmcc4_private.h
new file mode 100644 (file)
index 0000000..0ae18c4
--- /dev/null
@@ -0,0 +1,295 @@
+#ifndef _INC_PMCC4_PRIVATE_H_
+#define _INC_PMCC4_PRIVATE_H_
+
+/*-----------------------------------------------------------------------------
+ * pmcc4_private.h -
+ *
+ * Copyright (C) 2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>    /* support for tasklets */
+#include <linux/timer.h>        /* support for timer */
+#include <linux/workqueue.h>
+#include <linux/hdlc.h>
+
+#include "libsbew.h"
+#include "pmcc4_defs.h"
+#include "pmcc4_cpld.h"
+#include "musycc.h"
+#include "sbe_promformat.h"
+#include "comet.h"
+
+
+/* driver state */
+#define SBE_DRVR_INIT        0x0
+#define SBE_DRVR_AVAILABLE   0x69734F4E
+#define SBE_DRVR_DOWN        0x1
+
+/******************************************************************************
+ * MUSYCC Message Descriptor - coupled to hardware implementation, the first
+ * three u_int32 must not be reordered.
+ */
+
+struct mdesc
+{
+    volatile u_int32_t status;  /* Buffer Descriptor */
+    u_int32_t   data;           /* Data Pointer */
+    u_int32_t   next;           /* MUSYCC view of Next Pointer */
+    void       *mem_token;      /* Data */
+    struct mdesc *snext;
+};
+
+
+/*************************************************************************
+ * Private driver data structures, internal use only.
+ */
+
+struct c4_chan_info
+{
+    int         gchan;          /* channel number within group/port 0-31 */
+    int         channum;        /* absolute channel number 0-128 */
+    u_int8_t    status;
+#define TX_RECOVERY_MASK   0x0f
+#define TX_ONR_RECOVERY    0x01
+#define TX_BUFF_RECOVERY   0x02
+#define RX_RECOVERY_MASK   0xf0
+#define RX_ONR_RECOVERY    0x10
+
+    unsigned char ch_start_rx;
+#define CH_START_RX_NOW    1
+#define CH_START_RX_ONR    2
+#define CH_START_RX_BUF    3
+
+    unsigned char ch_start_tx;
+#define CH_START_TX_1ST    1
+#define CH_START_TX_ONR    2
+#define CH_START_TX_BUF    3
+
+    char        tx_full;        /* boolean */
+    short       txd_free;       /* count of TX Desc available */
+    short       txd_required;   /* count of TX Desc needed by mesg */
+    unsigned short rxd_num;     /* must support range up to 2000 */
+    unsigned short txd_num;     /* must support range up to 1000 */
+    int         rxix_irq_srv;
+
+    enum
+    {
+        UNASSIGNED,             /* AVAILABLE, NOTINUSE */
+        DOWN,                   /* ASSIGNED, NOTINUSE */
+        UP                      /* ASSIGNED and INUSE */
+    }           state;
+
+    struct c4_port_info *up;
+    void       *user;
+
+    struct work_struct ch_work;
+    struct mdesc *mdt;
+    struct mdesc *mdr;
+    struct mdesc *txd_irq_srv;
+    struct mdesc *txd_usr_add;
+
+#if 0
+    /*
+     * FUTURE CODE MIGHT SEPARATE TIMESLOT MAP SETUPS INTO SINGLE IOCTL and
+     * REMOVE MAPS FROM CHANNEL PARAMETER STRUCTURE
+     */
+    /*
+     * each byte in bitmask below represents one timeslot (bitmask[0] is for
+     * timeslot 0 and so on), each bit in the byte selects timeslot bits for
+     * this channel (0xff - whole timeslot, 0x7f - 56kbps mode)
+     */
+
+    u_int8_t    ts_bitmask[32];
+#endif
+    spinlock_t  ch_rxlock;
+    spinlock_t  ch_txlock;
+    atomic_t    tx_pending;
+
+    struct sbecom_chan_stats s;
+    struct sbecom_chan_param p;
+};
+typedef struct c4_chan_info mch_t;
+
+struct c4_port_info
+{
+
+    struct musycc_globalr *reg;
+    struct musycc_groupr *regram;
+    void       *regram_saved;   /* Original malloc value may have non-2KB
+                                 * boundary.  Need to save for use when
+                                 * freeing. */
+    comet_t    *cometbase;
+    struct sbe_card_info *up;
+
+    /*
+     * The workqueue is used for TX restart of ONR'd channels when in
+     * Transparent mode.
+     */
+
+    struct workqueue_struct *wq_port;   /* chan restart work queue */
+    struct semaphore sr_sem_busy;       /* service request exclusion
+                                         * semaphore */
+    struct semaphore sr_sem_wait;       /* service request handshake
+                                         * semaphore */
+    u_int32_t   sr_last;
+    short       openchans;
+    char        portnum;
+    char        group_is_set;   /* GROUP_INIT command issued to MUSYCC,
+                                 * otherwise SET_CHAN Ioctl fails */
+
+    mch_t      *chan[MUSYCC_NCHANS];
+    struct sbecom_port_param p;
+
+    /*
+     * The MUSYCC timeslot mappings are maintained within the driver and are
+     * modified and reloaded as each of a group's channels are configured.
+     */
+    u_int8_t    tsm[32];        /* tsm (time slot map) */
+    int         fifomap[32];
+};
+typedef struct c4_port_info mpi_t;
+
+
+#define COMET_OFFSET(x) (0x80000+(x)*0x10000)
+#define EEPROM_OFFSET   0xC0000
+#define ISPLD_OFFSET    0xD0000
+
+/* iSPLD control chip registers */
+#define ISPLD_MCSR  0x0
+#define ISPLD_MCLK  0x1
+#define ISPLD_LEDS  0x2
+#define ISPLD_INTR  0x3
+#define ISPLD_MAX   0x3
+
+struct sbe_card_info
+{
+    struct musycc_globalr *reg;
+    struct musycc_groupr *regram;
+    u_int32_t  *iqd_p;          /* pointer to dword aligned interrupt queue
+                                 * descriptors */
+    void       *iqd_p_saved;    /* Original malloc value may have non-dword
+                                 * aligned boundary.  Need to save for use
+                                 * when freeing. */
+    unsigned int iqp_headx, iqp_tailx;
+
+    struct semaphore sem_wdbusy;/* watchdog exclusion semaphore */
+    struct watchdog wd;         /* statically allocated watchdog structure */
+    atomic_t    bh_pending;     /* bh queued, but not yet running */
+    u_int32_t   brd_id;         /* unique PCI ID */
+    u_int16_t   hdw_bid;      /* on/board hardware ID */
+    unsigned short wdcount;
+    unsigned char max_port;
+    unsigned char brdno;        /* our board number */
+    unsigned char wd_notify;
+#define WD_NOTIFY_1TX       1
+#define WD_NOTIFY_BUF       2
+#define WD_NOTIFY_ONR       4
+    enum                        /* state as regards interrupt processing */
+    {
+        C_INIT,                 /* of-board-address not configured or are in
+                                 * process of being removed, don't access
+                                 * hardware */
+        C_IDLE,                 /* off-board-addresses are configured, but
+                                 * don't service interrupts, just clear them
+                                 * from hardware */
+        C_RUNNING               /* life is good, service away */
+    }           state;
+
+    struct sbe_card_info *next;
+    u_int32_t  *eeprombase;     /* mapped address of board's EEPROM */
+    c4cpld_t   *cpldbase;       /* mapped address of board's CPLD hardware */
+    char       *release;        /* SBE ID string w/in sbeRelease.c */
+    void       *hdw_info;
+#ifdef CONFIG_PROC_FS
+    struct proc_dir_entry *dir_dev;
+#endif
+
+    /* saved off interface assignments which bound a board */
+    hdlc_device *first_if;
+    hdlc_device *last_if;
+    short       first_channum, last_channum;
+
+    struct intlog
+    {
+        u_int32_t   this_status_new;
+        u_int32_t   last_status_new;
+        u_int32_t   drvr_intr_thcount;
+        u_int32_t   drvr_intr_bhcount;
+        u_int32_t   drvr_int_failure;
+    }           intlog;
+
+    mpi_t       port[MUSYCC_NPORTS];
+    char        devname[SBE_IFACETMPL_SIZE + 1];
+    atomic_t    tx_pending;
+    u_int32_t   alarmed[4];     /* dpm211 */
+
+#if defined(SBE_ISR_TASKLET)
+    struct tasklet_struct ci_musycc_isr_tasklet;
+#elif defined(SBE_ISR_IMMEDIATE)
+    struct tq_struct ci_musycc_isr_tq;
+#endif
+};
+typedef struct sbe_card_info ci_t;
+
+struct s_hdw_info
+{
+    u_int8_t    pci_busno;
+    u_int8_t    pci_slot;
+    u_int8_t    pci_pin[2];
+    u_int8_t    revid[2];
+    u_int8_t    mfg_info_sts;
+#define EEPROM_OK          0x00
+#define EEPROM_CRCERR      0x01
+    char        promfmt;        /* prom type, from sbe_promformat.h */
+
+    char        devname[SBE_IFACETMPL_SIZE];
+    struct pci_bus *bus;
+    struct net_device *ndev;
+    struct pci_dev *pdev[2];
+
+    unsigned long addr[2];
+    unsigned long addr_mapped[2];
+    unsigned long len[2];
+
+    union
+    {
+        char        data[128];
+        FLD_TYPE1   pft1;       /* prom field, type #1 */
+        FLD_TYPE2   pft2;       /* prom field, type #2 */
+    }           mfg_info;
+};
+typedef struct s_hdw_info hdw_info_t;
+
+/*****************************************************************/
+
+struct c4_priv
+{
+    int         channum;
+    struct sbe_card_info *ci;
+};
+
+
+/*****************************************************************/
+
+extern ci_t *c4_list;
+
+mch_t      *c4_find_chan (int);
+int         c4_set_chan (int channum, struct sbecom_chan_param *);
+int         c4_get_chan (int channum, struct sbecom_chan_param *);
+int         c4_get_chan_stats (int channum, struct sbecom_chan_stats *);
+
+#endif                          /* _INC_PMCC4_PRIVATE_H_ */
diff --git a/drivers/staging/cxt1e1/pmcc4_sysdep.h b/drivers/staging/cxt1e1/pmcc4_sysdep.h
new file mode 100644 (file)
index 0000000..697f194
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef _INC_PMCC4_SYSDEP_H_
+#define _INC_PMCC4_SYSDEP_H_
+
+/*-----------------------------------------------------------------------------
+ * pmcc4_sysdep.h -
+ *
+ * Copyright (C) 2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+/* reduce multiple autoconf entries to a single definition */
+
+#ifdef CONFIG_SBE_PMCC4_HDLC_V7_MODULE
+#undef CONFIG_SBE_PMCC4_HDLC_V7
+#define CONFIG_SBE_PMCC4_HDLC_V7  1
+#endif
+
+#ifdef CONFIG_SBE_PMCC4_NCOMM_MODULE
+#undef CONFIG_SBE_PMCC4_NCOMM
+#define CONFIG_SBE_PMCC4_NCOMM  1
+#endif
+
+
+/* FLUSH MACROS - if using ioremap_nocache(), then these can be NOOPS,
+ * otherwise a memory barrier needs to be inserted.
+ */
+
+#define FLUSH_PCI_READ()     rmb()
+#define FLUSH_PCI_WRITE()    wmb()
+#define FLUSH_MEM_READ()     rmb()
+#define FLUSH_MEM_WRITE()    wmb()
+
+
+/*
+ * System dependent callbacks routines, not inlined...
+ * For inlined system dependent routines, see include/sbecom_inlinux_linux.h
+ */
+
+/*
+ * passes received memory token back to the system, <user> is parameter from
+ * sd_new_chan() used to create the channel which the data arrived on
+ */
+
+void sd_recv_consume(void *token, size_t len, void *user);
+
+void        sd_disable_xmit (void *user);
+void        sd_enable_xmit (void *user);
+int         sd_line_is_ok (void *user);
+void        sd_line_is_up (void *user);
+void        sd_line_is_down (void *user);
+int         sd_queue_stopped (void *user);
+
+#endif                          /*** _INC_PMCC4_SYSDEP_H_ ***/
diff --git a/drivers/staging/cxt1e1/sbe_bid.h b/drivers/staging/cxt1e1/sbe_bid.h
new file mode 100644 (file)
index 0000000..1f49b40
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * $Id: sbe_bid.h,v 1.0 2005/09/28 00:10:09 rickd PMCC4_3_1B $
+ */
+
+#ifndef _INC_SBEBID_H_
+#define _INC_SBEBID_H_
+
+/*-----------------------------------------------------------------------------
+ * sbe_bid.h -
+ *
+ * Copyright (C) 2004-2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@sbei.com
+ * SBE, Inc.  San Ramon, California  U.S.A.
+ *
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 1.0 $
+ * Last changed on $Date: 2005/09/28 00:10:09 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: sbe_bid.h,v $
+ * Revision 1.0  2005/09/28 00:10:09  rickd
+ * Initial revision
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define SBE_BID_REG        0x00000000   /* Board ID Register */
+
+#define SBE_BID_256T3_E1         0x46   /* SBE wanPTMC-256T3 (E1 Version) */
+#define SBE_BID_256T3_T1         0x42   /* SBE wanPTMC-256T3 (T1 Version) */
+#define SBE_BID_2T3E3            0x43   /* SBE wanPMC-2T3E3 */
+#define SBE_BID_C1T3             0x45   /* SBE wanPMC-C1T3 */
+#define SBE_BID_C24TE1           0x47   /* SBE wanPTMC-C24TE1  */
+#define SBE_BID_C24TE1_RTM_24    0x48   /* C24TE1 RTM (24 Port) */
+#define SBE_BID_C24TE1_RTM_12    0x49   /* C24TE1 RTM (12 Port) */
+#define SBE_BID_C24TE1_RTM_12DSU 0x4A   /* C24TE1 RTM (12 Port/DSU) */
+#define SBE_BID_C24TE1_RTM_T3    0x4B   /* C24TE1 RTM (T3) */
+#define SBE_BID_C4T1E1           0x41   /* SBE wanPTMC-C4T1E1 */
+#define SBE_BID_HC4T1E1          0x44   /* SBE wanADAPT-HC4T1E1 */
+
+/* bogus temporary usage values */
+#define SBE_BID_PMC_C4T1E1       0xC4   /* SBE wanPMC-C4T1E1 (4 Port) */
+#define SBE_BID_PMC_C2T1E1       0xC2   /* SBE wanPMC-C2T1E1 (2 Port) */
+#define SBE_BID_PMC_C1T1E1       0xC1   /* SBE wanPMC-C1T1E1 (1 Port) */
+#define SBE_BID_PCI_C4T1E1       0x04   /* SBE wanPCI-C4T1E1 (4 Port) */
+#define SBE_BID_PCI_C2T1E1       0x02   /* SBE wanPCI-C2T1E1 (2 Port) */
+#define SBE_BID_PCI_C1T1E1       0x01   /* SBE wanPCI-C1T1E1 (1 Port) */
+
+#endif                          /*** _INC_SBEBID_H_ ***/
diff --git a/drivers/staging/cxt1e1/sbe_promformat.h b/drivers/staging/cxt1e1/sbe_promformat.h
new file mode 100644 (file)
index 0000000..746f81b
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * $Id: sbe_promformat.h,v 2.2 2005/09/28 00:10:09 rickd PMCC4_3_1B $
+ */
+
+#ifndef _INC_SBE_PROMFORMAT_H_
+#define _INC_SBE_PROMFORMAT_H_
+
+/*-----------------------------------------------------------------------------
+ * sbe_promformat.h - Contents of seeprom used by dvt and manufacturing tests
+ *
+ * Copyright (C) 2002-2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@sbei.com
+ * SBE, Inc.  San Ramon, California  U.S.A.
+ *
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 2.2 $
+ * Last changed on $Date: 2005/09/28 00:10:09 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: sbe_promformat.h,v $
+ * Revision 2.2  2005/09/28 00:10:09  rickd
+ * Add EEPROM sample from C4T1E1 board.
+ *
+ * Revision 2.1  2005/05/04 17:18:24  rickd
+ * Initial CI.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+/***
+ *  PMCC4 SAMPLE EEPROM IMAGE
+ *
+ *  eeprom[00]:  01 11 76 07  01 00 a0 d6
+ *  eeprom[08]:  22 34 56 3e  5b c1 1c 3e
+ *  eeprom[16]:  5b e1 b6 00  00 00 01 00
+ *  eeprom[24]:  00 08 46 d3  7b 5e a8 fb
+ *  eeprom[32]:  f7 ef df bf  7f 55 00 01
+ *  eeprom[40]:  02 04 08 10  20 40 80 ff
+ *  eeprom[48]:  fe fd fb f7  ef df bf 7f
+ *
+ ***/
+
+
+/*------------------------------------------------------------------------
+ *          Type 1 Format
+ * byte:
+ * 0    1  2    3  4      5   6   7    8  9  10    11 12 13 14    15 16 17 18
+ * -------------------------------------------------------------------------
+ * 01   11 76   SS SS     00 0A D6 <SERIAL NUM>    <Create TIME>  <Heatrun TIME>
+ *       SBE    SUB       SERIAL #    (BCD)         (time_t)       (time_t)
+ *       ID     VENDOR                              (format)       (format)
+ *
+ *  19 20 21 22    23 24 25 26
+ *  Heat Run        Heat Run
+ *  Iterations      Errors
+ *------------------------------------------------------------------------
+ *
+ *
+ *
+ *           Type 2 Format  - Added length, CRC in fixed position
+ * byte:
+ * 0    1  2       3  4  5  6      7  8        9  10     11 12 13 14 15 16
+ * -------------------------------------------------------------------------
+ * 02   00 1A      CC CC CC CC    11  76       07 03    00 0A D6 <SERIAL NUM>
+ *      Payload    SBE Crc32      SUB System   System    SERIAL/MAC
+ *      Length                    VENDOR ID    ID
+ *
+ *  17 18 19 20     21 22 23 24     25 26 27 28    29 39 31 32
+ * --------------------------------------------------------------------------
+ *  <Create TIME>   <Heatrun TIME>   Heat Run      Heat Run
+ *  (time_t)         (time_t)        Iterations    Errors
+ *
+ */
+
+#ifdef __cplusplus
+extern      "C"
+{
+#endif
+
+
+#define STRUCT_OFFSET(type, symbol)  ((long)&(((type *)0)->symbol))
+
+/*------------------------------------------------------------------------
+ *  Historically different Prom format types.
+ *
+ *  For diagnostic and failure purposes, do not create a type 0x00 or a
+ *  type 0xff
+ *------------------------------------------------------------------------
+ */
+#define PROM_FORMAT_Unk   (-1)
+#define PROM_FORMAT_TYPE1   1
+#define PROM_FORMAT_TYPE2   2
+
+
+/****** bit fields  for a type 1 formatted seeprom **************************/
+    typedef struct
+    {
+        char        type;       /* 0x00 */
+        char        Id[2];      /* 0x01-0x02 */
+        char        SubId[2];   /* 0x03-0x04 */
+        char        Serial[6];  /* 0x05-0x0a */
+        char        CreateTime[4];      /* 0x0b-0x0e */
+        char        HeatRunTime[4];     /* 0x0f-0x12 */
+        char        HeatRunIterations[4];       /* 0x13-0x16 */
+        char        HeatRunErrors[4];   /* 0x17-0x1a */
+        char        Crc32[4];   /* 0x1b-0x1e */
+    }           FLD_TYPE1;
+
+
+/****** bit fields  for a type 2 formatted seeprom **************************/
+    typedef struct
+    {
+        char        type;       /* 0x00 */
+        char        length[2];  /* 0x01-0x02 */
+        char        Crc32[4];   /* 0x03-0x06 */
+        char        Id[2];      /* 0x07-0x08 */
+        char        SubId[2];   /* 0x09-0x0a */
+        char        Serial[6];  /* 0x0b-0x10 */
+        char        CreateTime[4];      /* 0x11-0x14 */
+        char        HeatRunTime[4];     /* 0x15-0x18 */
+        char        HeatRunIterations[4];       /* 0x19-0x1c */
+        char        HeatRunErrors[4];   /* 0x1d-0x20 */
+    }           FLD_TYPE2;
+
+
+
+/***** this union allows us to access the seeprom as an array of bytes ***/
+/***** or as individual fields                                         ***/
+
+#define SBE_EEPROM_SIZE    128
+#define SBE_MFG_INFO_SIZE  sizeof(FLD_TYPE2)
+
+    typedef union
+    {
+        char        bytes[128];
+        FLD_TYPE1   fldType1;
+        FLD_TYPE2   fldType2;
+    }           PROMFORMAT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif                          /*** _INC_SBE_PROMFORMAT_H_ ***/
diff --git a/drivers/staging/cxt1e1/sbecom_inline_linux.h b/drivers/staging/cxt1e1/sbecom_inline_linux.h
new file mode 100644 (file)
index 0000000..2ab1eb1
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * $Id: sbecom_inline_linux.h,v 1.2 2007/08/15 22:51:35 rickd PMCC4_3_1B $
+ */
+
+#ifndef _INC_SBECOM_INLNX_H_
+#define _INC_SBECOM_INLNX_H_
+
+/*-----------------------------------------------------------------------------
+ * sbecom_inline_linux.h - SBE common Linux inlined routines
+ *
+ * Copyright (C) 2007  One Stop Systems, Inc.
+ * Copyright (C) 2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@onestopsystems.com
+ * One Stop Systems, Inc.  Escondido, California  U.S.A.
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 1.2 $
+ * Last changed on $Date: 2007/08/15 22:51:35 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: sbecom_inline_linux.h,v $
+ * Revision 1.2  2007/08/15 22:51:35  rickd
+ * Remove duplicate version.h entry.
+ *
+ * Revision 1.1  2007/08/15 22:50:29  rickd
+ * Update linux/config for 2.6.18 and later.
+ *
+ * Revision 1.0  2005/09/28 00:10:09  rickd
+ * Initial revision
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+#if defined (__FreeBSD__) || defined (__NetBSD__)
+#include <sys/types.h>
+#else
+#include <linux/types.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+#include <linux/config.h>
+#endif
+#if defined(CONFIG_SMP) && ! defined(__SMP__)
+#define __SMP__
+#endif
+#if defined(CONFIG_MODVERSIONS) && defined(MODULE) && ! defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+
+#ifdef MODULE
+#ifdef MODVERSIONS
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include <linux/modversions.h>
+#else
+#include <config/modversions.h>
+#endif
+#endif
+#include <linux/module.h>
+#endif
+#endif
+
+#include <linux/kernel.h>       /* resolves kmalloc references */
+#include <linux/skbuff.h>       /* resolves skb references */
+#include <linux/netdevice.h>    /* resolves dev_kree_skb_any */
+#include <asm/byteorder.h>      /* resolves cpu_to_le32 */
+
+#if 0
+
+/*** PORT POINT WARNING
+ ***
+ *** Under Linux 2.6 it has been found that compiler is re-ordering
+ *** in-lined pci_write_32() functions to the detrement of correct
+ *** hardware setup.  Therefore, inlining of PCI accesses has been
+ *** de-implemented, and subroutine calls have been implemented.
+ ***/
+
+static inline u_int32_t
+pci_read_32 (u_int32_t *p)
+{
+#ifdef FLOW_DEBUG
+    u_int32_t   v;
+
+    FLUSH_PCI_READ ();
+    v = le32_to_cpu (*p);
+    if (log_level >= LOG_DEBUG)
+        printk ("pci_read : %x = %x\n", (u_int32_t) p, v);
+    return v;
+#else
+                FLUSH_PCI_READ ();      /* */
+    return le32_to_cpu (*p);
+#endif
+}
+
+static inline void
+pci_write_32 (u_int32_t *p, u_int32_t v)
+{
+#ifdef FLOW_DEBUG
+    if (log_level >= LOG_DEBUG)
+        printk ("pci_write: %x = %x\n", (u_int32_t) p, v);
+#endif
+    *p = cpu_to_le32 (v);
+    FLUSH_PCI_WRITE ();             /* This routine is called from routines
+                                     * which do multiple register writes
+                                     * which themselves need flushing between
+                                     * writes in order to guarantee write
+                                     * ordering.  It is less code-cumbersome
+                                     * to flush here-in then to investigate
+                                     * and code the many other register
+                                     * writing routines. */
+}
+#else
+/* forward reference */
+u_int32_t   pci_read_32 (u_int32_t *p);
+void        pci_write_32 (u_int32_t *p, u_int32_t v);
+
+#endif
+
+
+/*
+ * system dependent callbacks
+ */
+
+/**********/
+/* malloc */
+/**********/
+
+static inline void *
+OS_kmalloc (size_t size)
+{
+    char       *ptr = kmalloc (size, GFP_KERNEL | GFP_DMA);
+
+    if (ptr)
+        memset (ptr, 0, size);
+    return ptr;
+}
+
+static inline void
+OS_kfree (void *x)
+{
+    kfree (x);
+}
+
+
+/****************/
+/* memory token */
+/****************/
+
+static inline void *
+OS_mem_token_alloc (size_t size)
+{
+    struct sk_buff *skb;
+
+    skb = dev_alloc_skb (size);
+    if (!skb)
+    {
+        //printk (KERN_WARNING "no mem in OS_mem_token_alloc !");
+        return 0;
+    }
+    return skb;
+}
+
+
+static inline void
+OS_mem_token_free (void *token)
+{
+    dev_kfree_skb_any (token);
+}
+
+
+static inline void
+OS_mem_token_free_irq (void *token)
+{
+    dev_kfree_skb_irq (token);
+}
+
+
+static inline void *
+OS_mem_token_data (void *token)
+{
+    return ((struct sk_buff *) token)->data;
+}
+
+
+static inline void *
+OS_mem_token_next (void *token)
+{
+    return 0;
+}
+
+
+static inline int
+OS_mem_token_len (void *token)
+{
+    return ((struct sk_buff *) token)->len;
+}
+
+
+static inline int
+OS_mem_token_tlen (void *token)
+{
+    return ((struct sk_buff *) token)->len;
+}
+
+
+/***************************************/
+/* virtual to physical addr conversion */
+/***************************************/
+
+static inline u_long
+OS_phystov (void *addr)
+{
+    return (u_long) __va (addr);
+}
+
+
+static inline u_long
+OS_vtophys (void *addr)
+{
+    return __pa (addr);
+}
+
+
+/**********/
+/* semops */
+/**********/
+
+void        OS_sem_init (void *, int);
+
+
+static inline void
+OS_sem_free (void *sem)
+{
+    /*
+     * NOOP - since semaphores structures predeclared w/in structures, no
+     * longer malloc'd
+     */
+}
+
+#define SD_SEM_TAKE(sem,desc)  down(sem)
+#define SD_SEM_GIVE(sem)       up(sem)
+#define SEM_AVAILABLE     1
+#define SEM_TAKEN         0
+
+
+/**********************/
+/* watchdog functions */
+/**********************/
+
+struct watchdog
+{
+    struct timer_list h;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+    struct tq_struct tq;
+#else
+    struct work_struct work;
+#endif
+    void       *softc;
+    void        (*func) (void *softc);
+    int         ticks;
+    int         init_tq;
+};
+
+
+static inline int
+OS_start_watchdog (struct watchdog * wd)
+{
+    wd->h.expires = jiffies + wd->ticks;
+    add_timer (&wd->h);
+    return 0;
+}
+
+
+static inline int
+OS_stop_watchdog (struct watchdog * wd)
+{
+    del_timer_sync (&wd->h);
+    return 0;
+}
+
+
+static inline int
+OS_free_watchdog (struct watchdog * wd)
+{
+    OS_stop_watchdog (wd);
+    OS_kfree (wd);
+    return 0;
+}
+
+
+/* sleep in microseconds */
+void        OS_uwait (int usec, char *description);
+void        OS_uwait_dummy (void);
+
+
+/* watchdog functions */
+int OS_init_watchdog(struct watchdog *wdp, void (*f) (void *), void *ci, int usec);
+
+
+#endif                          /*** _INC_SBECOM_INLNX_H_ ***/
diff --git a/drivers/staging/cxt1e1/sbecrc.c b/drivers/staging/cxt1e1/sbecrc.c
new file mode 100644 (file)
index 0000000..5123294
--- /dev/null
@@ -0,0 +1,137 @@
+/*   Based on "File Verification Using CRC" by Mark R. Nelson in Dr. Dobbs'
+ *   Journal, May 1992, pp. 64-67.  This algorithm generates the same CRC
+ *   values as ZMODEM and PKZIP
+ *
+ * Copyright (C) 2002-2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include <linux/types.h>
+#include "pmcc4_sysdep.h"
+#include "sbecom_inline_linux.h"
+#include "sbe_promformat.h"
+
+/* defines */
+#define CRC32_POLYNOMIAL                0xEDB88320L
+#define CRC_TABLE_ENTRIES                       256
+
+
+
+static      u_int32_t crcTableInit;
+
+#ifdef STATIC_CRC_TABLE
+static u_int32_t CRCTable[CRC_TABLE_ENTRIES];
+
+#endif
+
+
+/***************************************************************************
+*
+* genCrcTable - fills in CRCTable, as used by sbeCrc()
+*
+* RETURNS: N/A
+*
+* ERRNO: N/A
+***************************************************************************/
+
+static void
+genCrcTable (u_int32_t *CRCTable)
+{
+    int         ii, jj;
+    u_int32_t      crc;
+
+    for (ii = 0; ii < CRC_TABLE_ENTRIES; ii++)
+    {
+        crc = ii;
+        for (jj = 8; jj > 0; jj--)
+        {
+            if (crc & 1)
+                crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
+            else
+                crc >>= 1;
+        }
+        CRCTable[ii] = crc;
+    }
+
+    crcTableInit++;
+}
+
+
+/***************************************************************************
+*
+* sbeCrc - generates a CRC on a given buffer, and initial CRC
+*
+* This routine calculates the CRC for a buffer of data using the
+* table lookup method. It accepts an original value for the crc,
+* and returns the updated value. This permits "catenation" of
+* discontiguous buffers. An original value of 0 for the "first"
+* buffer is the norm.
+*
+* Based on "File Verification Using CRC" by Mark R. Nelson in Dr. Dobb's
+* Journal, May 1992, pp. 64-67.  This algorithm generates the same CRC
+* values as ZMODEM and PKZIP.
+*
+* RETURNS: calculated crc of block
+*
+*/
+
+void
+sbeCrc (u_int8_t *buffer,          /* data buffer to crc */
+        u_int32_t count,           /* length of block in bytes */
+        u_int32_t initialCrc,      /* starting CRC */
+        u_int32_t *result)
+{
+    u_int32_t     *tbl = 0;
+    u_int32_t      temp1, temp2, crc;
+
+    /*
+     * if table not yet created, do so. Don't care about "extra" time
+     * checking this everytime sbeCrc() is called, since CRC calculations are
+     * already time consuming
+     */
+    if (!crcTableInit)
+    {
+#ifdef STATIC_CRC_TABLE
+        tbl = &CRCTable;
+        genCrcTable (tbl);
+#else
+        tbl = (u_int32_t *) OS_kmalloc (CRC_TABLE_ENTRIES * sizeof (u_int32_t));
+        if (tbl == 0)
+        {
+            *result = 0;            /* dummy up return value due to malloc
+                                     * failure */
+            return;
+        }
+        genCrcTable (tbl);
+#endif
+    }
+    /* inverting bits makes ZMODEM & PKZIP compatible */
+    crc = initialCrc ^ 0xFFFFFFFFL;
+
+    while (count-- != 0)
+    {
+        temp1 = (crc >> 8) & 0x00FFFFFFL;
+        temp2 = tbl[((int) crc ^ *buffer++) & 0xff];
+        crc = temp1 ^ temp2;
+    }
+
+    crc ^= 0xFFFFFFFFL;
+
+    *result = crc;
+
+#ifndef STATIC_CRC_TABLE
+    crcTableInit = 0;
+    OS_kfree (tbl);
+#endif
+}
+
+/*** End-of-File ***/
diff --git a/drivers/staging/cxt1e1/sbeid.c b/drivers/staging/cxt1e1/sbeid.c
new file mode 100644 (file)
index 0000000..a2243b1
--- /dev/null
@@ -0,0 +1,217 @@
+/* Copyright (C) 2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include <linux/types.h>
+#include "pmcc4_sysdep.h"
+#include "sbecom_inline_linux.h"
+#include "libsbew.h"
+#include "pmcc4_private.h"
+#include "pmcc4.h"
+#include "sbe_bid.h"
+
+#ifdef SBE_INCLUDE_SYMBOLS
+#define STATIC
+#else
+#define STATIC  static
+#endif
+
+
+char       *
+sbeid_get_bdname (ci_t * ci)
+{
+    char       *np = 0;
+
+    switch (ci->brd_id)
+    {
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1):
+        np = "wanPTMC-256T3 <E1>";
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1):
+        np = "wanPTMC-256T3 <T1>";
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1):
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L):
+        np = "wanPMC-C4T1E1";
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1):
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L):
+        np = "wanPMC-C2T1E1";
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1):
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L):
+        np = "wanPMC-C1T1E1";
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1):
+        np = "wanPCI-C4T1E1";
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1):
+        np = "wanPCI-C2T1E1";
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1):
+        np = "wanPCI-C1T1E1";
+        break;
+    default:
+        /*** np = "<unknown>";  ***/
+        np = "wanPCI-CxT1E1";
+        break;
+    }
+
+    return np;
+}
+
+
+/* given the presetting of brd_id, set the corresponding hdw_id */
+
+void
+sbeid_set_hdwbid (ci_t * ci)
+{
+    /*
+     * set SBE's unique hardware identification (for legacy boards might not
+     * have this register implemented)
+     */
+
+    switch (ci->brd_id)
+    {
+        case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1):
+        ci->hdw_bid = SBE_BID_256T3_E1; /* 0x46 - SBE wanPTMC-256T3 (E1
+                                         * Version) */
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1):
+        ci->hdw_bid = SBE_BID_256T3_T1; /* 0x42 - SBE wanPTMC-256T3 (T1
+                                         * Version) */
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1):
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L):
+        /*
+         * This Board ID is a generic identification.  Use the found number
+         * of ports to further define this hardware.
+         */
+        switch (ci->max_port)
+        {
+        default:                    /* shouldn't need a default, but have one
+                                     * anyway */
+        case 4:
+            ci->hdw_bid = SBE_BID_PMC_C4T1E1;   /* 0xC4 - SBE wanPMC-C4T1E1 */
+            break;
+        case 2:
+            ci->hdw_bid = SBE_BID_PMC_C2T1E1;   /* 0xC2 - SBE wanPMC-C2T1E1 */
+            ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1);
+            break;
+        case 1:
+            ci->hdw_bid = SBE_BID_PMC_C1T1E1;   /* 0xC1 - SBE wanPMC-C1T1E1 */
+            ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1);
+            break;
+        }
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1):
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L):
+        ci->hdw_bid = SBE_BID_PMC_C2T1E1;       /* 0xC2 - SBE wanPMC-C2T1E1 */
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1):
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L):
+        ci->hdw_bid = SBE_BID_PMC_C1T1E1;       /* 0xC1 - SBE wanPMC-C1T1E1 */
+        break;
+#ifdef SBE_PMCC4_ENABLE
+        /*
+         * This case is entered as a result of the inability to obtain the
+         * <bid> from the board's EEPROM.  Assume a PCI board and set
+         * <hdsbid> according to the number ofr found ports.
+         */
+    case 0:
+        /* start by assuming 4-port for ZERO casing */
+        ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1);
+        /* drop thru to set hdw_bid and alternate PCI CxT1E1 settings */
+#endif
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1):
+        /*
+         * This Board ID is a generic identification.  Use the number of
+         * found ports to further define this hardware.
+         */
+        switch (ci->max_port)
+        {
+        default:                    /* shouldn't need a default, but have one
+                                     * anyway */
+        case 4:
+            ci->hdw_bid = SBE_BID_PCI_C4T1E1;   /* 0x04 - SBE wanPCI-C4T1E1 */
+            break;
+        case 2:
+            ci->hdw_bid = SBE_BID_PCI_C2T1E1;   /* 0x02 - SBE wanPCI-C2T1E1 */
+            ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1);
+            break;
+        case 1:
+            ci->hdw_bid = SBE_BID_PCI_C1T1E1;   /* 0x01 - SBE wanPCI-C1T1E1 */
+            ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1);
+            break;
+        }
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1):
+        ci->hdw_bid = SBE_BID_PCI_C2T1E1;       /* 0x02 - SBE wanPCI-C2T1E1 */
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1):
+        ci->hdw_bid = SBE_BID_PCI_C1T1E1;       /* 0x01 - SBE wanPCI-C1T1E1 */
+        break;
+    default:
+        /*** bid = "<unknown>";  ***/
+        ci->hdw_bid = SBE_BID_PMC_C4T1E1;       /* 0x41 - SBE wanPTMC-C4T1E1 */
+        break;
+    }
+}
+
+/* given the presetting of hdw_bid, set the corresponding brd_id */
+
+void
+sbeid_set_bdtype (ci_t * ci)
+{
+    /* set SBE's unique PCI VENDOR/DEVID */
+    switch (ci->hdw_bid)
+    {
+        case SBE_BID_C1T3:      /* SBE wanPMC-C1T3 */
+        ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T3);
+        break;
+    case SBE_BID_C24TE1:            /* SBE wanPTMC-C24TE1 */
+        ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_C24TE1);
+        break;
+    case SBE_BID_256T3_E1:          /* SBE wanPTMC-256T3 E1 Version */
+        ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1);
+        break;
+    case SBE_BID_256T3_T1:          /* SBE wanPTMC-256T3 T1 Version */
+        ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1);
+        break;
+    case SBE_BID_PMC_C4T1E1:        /* 0xC4 - SBE wanPMC-C4T1E1 */
+        ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1);
+        break;
+    case SBE_BID_PMC_C2T1E1:        /* 0xC2 - SBE wanPMC-C2T1E1 */
+        ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1);
+        break;
+    case SBE_BID_PMC_C1T1E1:        /* 0xC1 - SBE wanPMC-C1T1E1 */
+        ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1);
+        break;
+    case SBE_BID_PCI_C4T1E1:        /* 0x04 - SBE wanPCI-C4T1E1 */
+        ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1);
+        break;
+    case SBE_BID_PCI_C2T1E1:        /* 0x02 - SBE wanPCI-C2T1E1 */
+        ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1);
+        break;
+    case SBE_BID_PCI_C1T1E1:        /* 0x01 - SBE wanPCI-C1T1E1 */
+        ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1);
+        break;
+
+    default:
+        /*** hdw_bid = "<unknown>";  ***/
+        ci->brd_id = SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1);
+        break;
+    }
+}
+
+
+/***  End-of-File  ***/
diff --git a/drivers/staging/cxt1e1/sbeproc.c b/drivers/staging/cxt1e1/sbeproc.c
new file mode 100644 (file)
index 0000000..61ca639
--- /dev/null
@@ -0,0 +1,358 @@
+/* Copyright (C) 2004-2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include "pmcc4_sysdep.h"
+#include "sbecom_inline_linux.h"
+#include "pmcc4_private.h"
+#include "sbeproc.h"
+
+/* forwards */
+void        sbecom_get_brdinfo (ci_t *, struct sbe_brd_info *, u_int8_t *);
+extern struct s_hdw_info hdw_info[MAX_BOARDS];
+
+#ifdef CONFIG_PROC_FS
+
+/********************************************************************/
+/* procfs stuff                                                     */
+/********************************************************************/
+
+
+void
+sbecom_proc_brd_cleanup (ci_t * ci)
+{
+    if (ci->dir_dev)
+    {
+       char dir[7 + SBE_IFACETMPL_SIZE + 1];
+       snprintf(dir, sizeof(dir), "driver/%s", ci->devname);
+        remove_proc_entry("info", ci->dir_dev);
+        remove_proc_entry(dir, NULL);
+        ci->dir_dev = NULL;
+    }
+}
+
+
+static int
+sbecom_proc_get_sbe_info (char *buffer, char **start, off_t offset,
+                          int length, int *eof, void *priv)
+{
+    ci_t       *ci = (ci_t *) priv;
+    int         len = 0;
+    char       *spd;
+    struct sbe_brd_info *bip;
+
+    if (!(bip = OS_kmalloc (sizeof (struct sbe_brd_info))))
+    {
+        return -ENOMEM;
+    }
+#if 0
+    /** RLD DEBUG **/
+    printk (">> sbecom_proc_get_sbe_info: entered, offset %d. length %d.\n",
+            (int) offset, (int) length);
+#endif
+
+    {
+        hdw_info_t *hi = &hdw_info[ci->brdno];
+
+        u_int8_t *bsn = 0;
+
+        switch (hi->promfmt)
+        {
+        case PROM_FORMAT_TYPE1:
+            bsn = (u_int8_t *) hi->mfg_info.pft1.Serial;
+            break;
+        case PROM_FORMAT_TYPE2:
+            bsn = (u_int8_t *) hi->mfg_info.pft2.Serial;
+            break;
+        }
+
+        sbecom_get_brdinfo (ci, bip, bsn);
+    }
+
+#if 0
+    /** RLD DEBUG **/
+    printk (">> sbecom_get_brdinfo: returned, first_if %p <%s> last_if %p <%s>\n",
+            (char *) &bip->first_iname, (char *) &bip->first_iname,
+            (char *) &bip->last_iname, (char *) &bip->last_iname);
+#endif
+    len += sprintf (buffer + len, "Board Type:    ");
+    switch (bip->brd_id)
+    {
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T3):
+        len += sprintf (buffer + len, "wanPMC-C1T3");
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1):
+        len += sprintf (buffer + len, "wanPTMC-256T3 <E1>");
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1):
+        len += sprintf (buffer + len, "wanPTMC-256T3 <T1>");
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_C24TE1):
+        len += sprintf (buffer + len, "wanPTMC-C24TE1");
+        break;
+
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1):
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L):
+        len += sprintf (buffer + len, "wanPMC-C4T1E1");
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1):
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L):
+        len += sprintf (buffer + len, "wanPMC-C2T1E1");
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1):
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L):
+        len += sprintf (buffer + len, "wanPMC-C1T1E1");
+        break;
+
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1):
+        len += sprintf (buffer + len, "wanPCI-C4T1E1");
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1):
+        len += sprintf (buffer + len, "wanPCI-C2T1E1");
+        break;
+    case SBE_BOARD_ID (PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1):
+        len += sprintf (buffer + len, "wanPCI-C1T1E1");
+        break;
+
+    default:
+        len += sprintf (buffer + len, "unknown");
+        break;
+    }
+    len += sprintf (buffer + len, "  [%08X]\n", bip->brd_id);
+
+    len += sprintf (buffer + len, "Board Number:  %d\n", bip->brdno);
+    len += sprintf (buffer + len, "Hardware ID:   0x%02X\n", ci->hdw_bid);
+    len += sprintf (buffer + len, "Board SN:      %06X\n", bip->brd_sn);
+    len += sprintf (buffer + len, "Board MAC:     %02X-%02X-%02X-%02X-%02X-%02X\n",
+           bip->brd_mac_addr[0], bip->brd_mac_addr[1], bip->brd_mac_addr[2],
+          bip->brd_mac_addr[3], bip->brd_mac_addr[4], bip->brd_mac_addr[5]);
+    len += sprintf (buffer + len, "Ports:         %d\n", ci->max_port);
+    len += sprintf (buffer + len, "Channels:      %d\n", bip->brd_chan_cnt);
+#if 1
+    len += sprintf (buffer + len, "Interface:     %s -> %s\n",
+                    (char *) &bip->first_iname, (char *) &bip->last_iname);
+#else
+    len += sprintf (buffer + len, "Interface:     <not available> 1st %p lst %p\n",
+                    (char *) &bip->first_iname, (char *) &bip->last_iname);
+#endif
+
+    switch (bip->brd_pci_speed)
+    {
+    case BINFO_PCI_SPEED_33:
+        spd = "33Mhz";
+        break;
+    case BINFO_PCI_SPEED_66:
+        spd = "66Mhz";
+        break;
+    default:
+        spd = "<not available>";
+        break;
+    }
+    len += sprintf (buffer + len, "PCI Bus Speed: %s\n", spd);
+    len += sprintf (buffer + len, "Release:       %s\n", ci->release);
+
+#ifdef SBE_PMCC4_ENABLE
+    {
+        extern int max_mru;
+#if 0
+        extern int max_chans_used;
+        extern int max_mtu;
+#endif
+        extern int max_rxdesc_used, max_txdesc_used;
+
+        len += sprintf (buffer + len, "\nmax_mru:         %d\n", max_mru);
+#if 0
+        len += sprintf (buffer + len, "\nmax_chans_used:  %d\n", max_chans_used);
+        len += sprintf (buffer + len, "max_mtu:         %d\n", max_mtu);
+#endif
+        len += sprintf (buffer + len, "max_rxdesc_used: %d\n", max_rxdesc_used);
+        len += sprintf (buffer + len, "max_txdesc_used: %d\n", max_txdesc_used);
+    }
+#endif
+
+    OS_kfree (bip);                 /* cleanup */
+
+    /***
+     * How to be a proc read function
+     * ------------------------------
+     * Prototype:
+     *    int f(char *buffer, char **start, off_t offset,
+     *          int count, int *peof, void *dat)
+     *
+     * Assume that the buffer is "count" bytes in size.
+     *
+     * If you know you have supplied all the data you
+     * have, set *peof.
+     *
+     * You have three ways to return data:
+     * 0) Leave *start = NULL.  (This is the default.)
+     *    Put the data of the requested offset at that
+     *    offset within the buffer.  Return the number (n)
+     *    of bytes there are from the beginning of the
+     *    buffer up to the last byte of data.  If the
+     *    number of supplied bytes (= n - offset) is
+     *    greater than zero and you didn't signal eof
+     *    and the reader is prepared to take more data
+     *    you will be called again with the requested
+     *    offset advanced by the number of bytes
+     *    absorbed.  This interface is useful for files
+     *    no larger than the buffer.
+     * 1) Set *start = an unsigned long value less than
+     *    the buffer address but greater than zero.
+     *    Put the data of the requested offset at the
+     *    beginning of the buffer.  Return the number of
+     *    bytes of data placed there.  If this number is
+     *    greater than zero and you didn't signal eof
+     *    and the reader is prepared to take more data
+     *    you will be called again with the requested
+     *    offset advanced by *start.  This interface is
+     *    useful when you have a large file consisting
+     *    of a series of blocks which you want to count
+     *    and return as wholes.
+     *    (Hack by Paul.Russell@rustcorp.com.au)
+     * 2) Set *start = an address within the buffer.
+     *    Put the data of the requested offset at *start.
+     *    Return the number of bytes of data placed there.
+     *    If this number is greater than zero and you
+     *    didn't signal eof and the reader is prepared to
+     *    take more data you will be called again with the
+     *    requested offset advanced by the number of bytes
+     *    absorbed.
+     */
+
+#if 1
+    /* #4 - intepretation of above = set EOF, return len */
+    *eof = 1;
+#endif
+
+#if 0
+    /*
+     * #1 - from net/wireless/atmel.c RLD NOTE -there's something wrong with
+     * this plagarized code which results in this routine being called TWICE.
+     * The second call returns ZERO, resulting in hidden failure, but at
+     * least only a single message set is being displayed.
+     */
+    if (len <= offset + length)
+        *eof = 1;
+    *start = buffer + offset;
+    len -= offset;
+    if (len > length)
+        len = length;
+    if (len < 0)
+        len = 0;
+#endif
+
+#if 0                               /* #2 from net/tokenring/olympic.c +
+                                     * lanstreamer.c */
+    {
+        off_t       begin = 0;
+        int         size = 0;
+        off_t       pos = 0;
+
+        size = len;
+        pos = begin + size;
+        if (pos < offset)
+        {
+            len = 0;
+            begin = pos;
+        }
+        *start = buffer + (offset - begin);     /* Start of wanted data */
+        len -= (offset - begin);    /* Start slop */
+        if (len > length)
+            len = length;           /* Ending slop */
+    }
+#endif
+
+#if 0                               /* #3 from
+                                     * char/ftape/lowlevel/ftape-proc.c */
+    len = strlen (buffer);
+    *start = NULL;
+    if (offset + length >= len)
+        *eof = 1;
+    else
+        *eof = 0;
+#endif
+
+#if 0
+    printk (">> proc_fs: returned len = %d., start %p\n", len, start);  /* RLD DEBUG */
+#endif
+
+/***
+   using NONE: returns = 314.314.314.
+   using #1  : returns = 314, 0.
+   using #2  : returns = 314, 0, 0.
+   using #3  : returns = 314, 314.
+   using #4  : returns = 314, 314.
+***/
+
+    return len;
+}
+
+/* initialize the /proc subsystem for the specific SBE driver */
+
+int         __init
+sbecom_proc_brd_init (ci_t * ci)
+{
+    struct proc_dir_entry *e;
+    char dir[7 + SBE_IFACETMPL_SIZE + 1];
+
+    /* create a directory in the root procfs */
+    snprintf(dir, sizeof(dir), "driver/%s", ci->devname);
+    ci->dir_dev = proc_mkdir(dir, NULL);
+    if (!ci->dir_dev)
+    {
+        printk (KERN_ERR "%s: Unable to create directory /proc/driver/%s\n",
+                THIS_MODULE->name, ci->devname);
+        goto fail;
+    }
+    e = create_proc_read_entry ("info", S_IFREG | S_IRUGO,
+                                ci->dir_dev, sbecom_proc_get_sbe_info, ci);
+    if (!e)
+    {
+        printk (KERN_ERR "%s: Unable to create entry /proc/driver/%s/info\n",
+                THIS_MODULE->name, ci->devname);
+        goto fail;
+    }
+    return 0;
+
+fail:
+    sbecom_proc_brd_cleanup (ci);
+    return 1;
+}
+
+#else                           /*** ! CONFIG_PROC_FS ***/
+
+/* stubbed off dummy routines */
+
+void
+sbecom_proc_brd_cleanup (ci_t * ci)
+{
+}
+
+int         __init
+sbecom_proc_brd_init (ci_t * ci)
+{
+    return 0;
+}
+
+#endif                          /*** CONFIG_PROC_FS ***/
+
+
+/*** End-of-File ***/
diff --git a/drivers/staging/cxt1e1/sbeproc.h b/drivers/staging/cxt1e1/sbeproc.h
new file mode 100644 (file)
index 0000000..4aa53f4
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * $Id: sbeproc.h,v 1.2 2005/10/17 23:55:28 rickd PMCC4_3_1B $
+ */
+
+#ifndef _INC_SBEPROC_H_
+#define _INC_SBEPROC_H_
+
+/*-----------------------------------------------------------------------------
+ * sbeproc.h -
+ *
+ * Copyright (C) 2004-2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@sbei.com
+ * SBE, Inc.  San Ramon, California  U.S.A.
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 1.2 $
+ * Last changed on $Date: 2005/10/17 23:55:28 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: sbeproc.h,v $
+ * Revision 1.2  2005/10/17 23:55:28  rickd
+ * sbecom_proc_brd_init() is an declared an __init function.
+ *
+ * Revision 1.1  2005/09/28 00:10:09  rickd
+ * Remove unneeded inclusion of c4_private.h.
+ *
+ * Revision 1.0  2005/05/10 22:21:46  rickd
+ * Initial check-in.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+#ifdef CONFIG_PROC_FS
+#ifdef __KERNEL__
+void        sbecom_proc_brd_cleanup (ci_t *);
+int __init  sbecom_proc_brd_init (ci_t *);
+
+#endif                          /*** __KERNEL__ ***/
+#endif                          /*** CONFIG_PROC_FS ***/
+#endif                          /*** _INC_SBEPROC_H_ ***/
diff --git a/drivers/staging/cxt1e1/sbew_ioc.h b/drivers/staging/cxt1e1/sbew_ioc.h
new file mode 100644 (file)
index 0000000..14d3719
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * $Id: sbew_ioc.h,v 1.0 2005/09/28 00:10:10 rickd PMCC4_3_1B $
+ */
+
+#ifndef _INC_SBEWIOC_H_
+#define _INC_SBEWIOC_H_
+
+/*-----------------------------------------------------------------------------
+ * sbew_ioc.h -
+ *
+ * Copyright (C) 2002-2005  SBE, Inc.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * For further information, contact via email: support@sbei.com
+ * SBE, Inc.  San Ramon, California  U.S.A.
+ *
+ *-----------------------------------------------------------------------------
+ * RCS info:
+ * RCS revision: $Revision: 1.0 $
+ * Last changed on $Date: 2005/09/28 00:10:10 $
+ * Changed by $Author: rickd $
+ *-----------------------------------------------------------------------------
+ * $Log: sbew_ioc.h,v $
+ * Revision 1.0  2005/09/28 00:10:10  rickd
+ * Initial revision
+ *
+ * Revision 1.6  2005/01/11 18:41:01  rickd
+ * Add BRDADDR_GET Ioctl.
+ *
+ * Revision 1.5  2004/09/16 18:55:59  rickd
+ * Start setting up for generic framer configuration Ioctl by switch
+ * from tect3_framer_param[] to sbecom_framer_param[].
+ *
+ * Revision 1.4  2004/06/28 17:58:15  rickd
+ * Rename IOC_TSMAP_[GS] to IOC_TSIOC_[GS] to support need for
+ * multiple formats of data when setting up TimeSlots.
+ *
+ * Revision 1.3  2004/06/22 21:18:13  rickd
+ * read_vec now() ONLY handles a single common wrt_vec array.
+ *
+ * Revision 1.1  2004/06/10 18:11:34  rickd
+ * Add IID_GET Ioctl reference.
+ *
+ * Revision 1.0  2004/06/08 22:59:38  rickd
+ * Initial revision
+ *
+ * Revision 2.0  2004/06/07 17:49:47  rickd
+ * Initial library release following merge of wanc1t3/wan256 into
+ * common elements for lib.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef __KERNEL__
+#include <sys/types.h>
+#endif
+#ifdef SunOS
+#include <sys/ioccom.h>
+#else
+#include <linux/ioctl.h>
+#endif
+
+#ifdef __cplusplus
+extern      "C"
+{
+#endif
+
+#define SBE_LOCKFILE   "/tmp/.sbewan.LCK"
+
+#define SBE_IOC_COOKIE     0x19780926
+#define SBE_IOC_MAGIC      ('s')
+
+/* IOW write - data has to go into driver from application */
+/* IOR read - data has to be returned to application from driver */
+
+/*
+ * Note: for an IOWR Ioctl, the read and write data do not have to
+ * be the same size, but the entity declared within the IOC must be
+ * the larger of the two.
+ */
+
+#define SBE_IOC_LOGLEVEL       _IOW(SBE_IOC_MAGIC, 0x00, int)
+#define SBE_IOC_CHAN_NEW       _IOW(SBE_IOC_MAGIC, 0x01,int)    /* unused */
+#define SBE_IOC_CHAN_UP        _IOW(SBE_IOC_MAGIC, 0x02,int)    /* unused */
+#define SBE_IOC_CHAN_DOWN      _IOW(SBE_IOC_MAGIC, 0x03,int)    /* unused */
+#define SBE_IOC_CHAN_GET       _IOWR(SBE_IOC_MAGIC,0x04, struct sbecom_chan_param)
+#define SBE_IOC_CHAN_SET       _IOW(SBE_IOC_MAGIC, 0x05, struct sbecom_chan_param)
+#define SBE_IOC_CHAN_GET_STAT  _IOWR(SBE_IOC_MAGIC,0x06, struct sbecom_chan_stats)
+#define SBE_IOC_CHAN_DEL_STAT  _IOW(SBE_IOC_MAGIC, 0x07, int)
+#define SBE_IOC_PORTS_ENABLE   _IOW(SBE_IOC_MAGIC, 0x0A, int)
+#define SBE_IOC_PORT_GET       _IOWR(SBE_IOC_MAGIC,0x0C, struct sbecom_port_param)
+#define SBE_IOC_PORT_SET       _IOW(SBE_IOC_MAGIC, 0x0D, struct sbecom_port_param)
+#define SBE_IOC_READ_VEC       _IOWR(SBE_IOC_MAGIC,0x10, struct sbecom_wrt_vec)
+#define SBE_IOC_WRITE_VEC      _IOWR(SBE_IOC_MAGIC,0x11, struct sbecom_wrt_vec)
+#define SBE_IOC_GET_SN         _IOR(SBE_IOC_MAGIC, 0x12, u_int32_t)
+#define SBE_IOC_RESET_DEV      _IOW(SBE_IOC_MAGIC, 0x13, int)
+#define SBE_IOC_FRAMER_GET     _IOWR(SBE_IOC_MAGIC,0x14, struct sbecom_framer_param)
+#define SBE_IOC_FRAMER_SET     _IOW(SBE_IOC_MAGIC, 0x15, struct sbecom_framer_param)
+#define SBE_IOC_CARD_GET       _IOR(SBE_IOC_MAGIC, 0x20, struct sbecom_card_param)
+#define SBE_IOC_CARD_SET       _IOW(SBE_IOC_MAGIC, 0x21, struct sbecom_card_param)
+#define SBE_IOC_CARD_GET_STAT  _IOR(SBE_IOC_MAGIC, 0x22, struct temux_card_stats)
+#define SBE_IOC_CARD_DEL_STAT  _IO(SBE_IOC_MAGIC,  0x23)
+#define SBE_IOC_CARD_CHAN_STAT _IOR(SBE_IOC_MAGIC, 0x24, struct sbecom_chan_stats)
+#define SBE_IOC_CARD_BLINK     _IOW(SBE_IOC_MAGIC, 0x30, int)
+#define SBE_IOC_DRVINFO_GET    _IOWR(SBE_IOC_MAGIC,0x31, struct sbe_drv_info)
+#define SBE_IOC_BRDINFO_GET    _IOR(SBE_IOC_MAGIC, 0x32, struct sbe_brd_info)
+#define SBE_IOC_IID_GET        _IOWR(SBE_IOC_MAGIC,0x33, struct sbe_iid_info)
+#define SBE_IOC_BRDADDR_GET    _IOWR(SBE_IOC_MAGIC, 0x34, struct sbe_brd_addr)
+
+#ifdef NOT_YET_COMMON
+#define SBE_IOC_TSIOC_GET      _IOWR(SBE_IOC_MAGIC,0x16, struct wanc1t3_ts_param)
+#define SBE_IOC_TSIOC_SET      _IOW(SBE_IOC_MAGIC, 0x17, struct wanc1t3_ts_param)
+#endif
+
+/*
+ * Restrict SBE_IOC_WRITE_VEC & READ_VEC to a single parameter pair, application
+ * then must issue multiple Ioctls for large blocks of contiguous data.
+ */
+
+#define SBE_IOC_MAXVEC    1
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif                          /*** _INC_SBEWIOC_H_ ***/