summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorAlex Feldman <alex@cvs.openbsd.org>2004-06-26 06:42:34 +0000
committerAlex Feldman <alex@cvs.openbsd.org>2004-06-26 06:42:34 +0000
commitef30e9ded064276643aa397a8ebf9264045b7d18 (patch)
treebcd74bdff94e669caddb50d42fddbcaf76832eaf /sys/dev/pci
parent749c2277f90ee646890cd949efcaa998dbc6fb69 (diff)
Sangoma Network Device driver for AFT series card (initiali version).
ok mcbride@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/if_san_common.c401
-rw-r--r--sys/dev/pci/if_san_common.h400
-rw-r--r--sys/dev/pci/if_san_front_end.h217
-rw-r--r--sys/dev/pci/if_san_obsd.c393
-rw-r--r--sys/dev/pci/if_san_obsd.h109
-rw-r--r--sys/dev/pci/if_san_te1.c3987
-rw-r--r--sys/dev/pci/if_san_te1.h987
-rw-r--r--sys/dev/pci/if_san_xilinx.c3535
-rw-r--r--sys/dev/pci/if_san_xilinx.h667
-rw-r--r--sys/dev/pci/if_sandrv.c1584
-rw-r--r--sys/dev/pci/if_sandrv.h331
11 files changed, 12611 insertions, 0 deletions
diff --git a/sys/dev/pci/if_san_common.c b/sys/dev/pci/if_san_common.c
new file mode 100644
index 00000000000..349cd0a45e5
--- /dev/null
+++ b/sys/dev/pci/if_san_common.c
@@ -0,0 +1,401 @@
+/*-
+ * Copyright (c) 2001-2004 Sangoma Technologies (SAN)
+ * All rights reserved. www.sangoma.com
+ *
+ * This code is written by Alex Feldman <al.feldman@sangoma.com> for SAN.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sangoma Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SANGOMA TECHNOLOGIES AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+# include </usr/include/bitstring.h>
+# include <sys/types.h>
+# include <sys/param.h>
+# include <sys/systm.h>
+# include <sys/syslog.h>
+# include <sys/ioccom.h>
+# include <sys/conf.h>
+# include <sys/malloc.h>
+# include <sys/errno.h>
+# include <sys/exec.h>
+# include <sys/mbuf.h>
+# include <sys/socket.h>
+# include <sys/kernel.h>
+# include <sys/time.h>
+# include <sys/timeout.h>
+
+# include <net/bpf.h>
+# include <net/bpfdesc.h>
+# include <net/if_dl.h>
+# include <net/if_types.h>
+# include <net/if.h>
+# include <net/netisr.h>
+# include <net/route.h>
+# include <net/if_media.h>
+# include <net/ppp_defs.h>
+# include <net/if_ppp.h>
+# include <net/if_sppp.h>
+# include <netinet/in_systm.h>
+# include <netinet/in.h>
+# include <netinet/in_var.h>
+# include <netinet/udp.h>
+# include <netinet/ip.h>
+
+# include <dev/pci/if_san_common.h>
+# include <dev/pci/if_san_obsd.h>
+
+/****** Defines & Macros ****************************************************/
+
+#ifdef _DEBUG_
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+/****** Function Prototypes *************************************************/
+
+/* WAN link driver entry points */
+#if 0
+static int shutdown(sdla_t *card);
+#endif
+
+/* Miscellaneous functions */
+static int wan_ioctl(struct ifnet* ifp, int cmd, struct ifreq* ifr);
+static int sdla_isr (void* dev_id);
+
+static void release_hw (sdla_t *card);
+
+static int wan_ioctl_dump(sdla_t* card, void* u_dump);
+static int wan_ioctl_hwprobe(struct ifnet* ifp, void* u_def);
+
+/****** Global Data **********************************************************
+ * Note: All data must be explicitly initialized!!!
+ */
+
+/* private data */
+extern char *san_drvname;
+LIST_HEAD(, sdla) wan_cardlist = LIST_HEAD_INITIALIZER(&wan_cardlist);
+
+#if 0
+static san_detach(void)
+{
+ wanpipe_common_t *common;
+ sdla_t *card, *tmp_card;
+ int err = 0;
+
+ card = LIST_FIRST(&wan_cardlist);
+ while (card){
+ if (card->disable_comm){
+ card->disable_comm(card);
+ }
+ while ((common = LIST_FIRST(&card->dev_head))){
+ LIST_REMOVE(common, next);
+ if (card->del_if){
+ struct ifnet *ifp = (struct ifnet*)&common->ifp;
+ log(LOG_INFO, "%s: Deleting interface...\n",
+ ifp->if_xname);
+ card->del_if(card, ifp);
+ }
+ }
+ log(LOG_INFO, "%s: Shutdown device\n", card->devname);
+ shutdown(card);
+ tmp_card = card;
+ card = LIST_NEXT(card, next);
+ LIST_REMOVE(tmp_card, next);
+ free(tmp_card, M_DEVBUF);
+ }
+
+ log(LOG_INFO, "\n");
+ log(LOG_INFO, "%s: WANPIPE Generic Modules Unloaded.\n",
+ san_drvname);
+
+ err = sdladrv_exit();
+ return err;
+}
+#endif
+
+
+int san_dev_attach (void *hw, u_int8_t *devname)
+{
+ sdla_t *card;
+ wanpipe_common_t *common = NULL;
+ int err = 0;
+
+ card=malloc(sizeof(sdla_t), M_DEVBUF, M_NOWAIT);
+ if (!card){
+ log(LOG_INFO, "%s: Failed allocate new card!\n",
+ san_drvname);
+ return -EINVAL;
+ }
+ memset(card, 0, sizeof(sdla_t));
+ card->magic = WANPIPE_MAGIC;
+ wanpipe_generic_name(card, card->devname);
+ bcopy(card->devname, devname, strlen(card->devname));
+ card->hw = hw;
+ LIST_INIT(&card->dev_head);
+
+ sdla_getcfg(card->hw, SDLA_CARDTYPE, &card->type);
+ if (sdla_is_te1(card->hw)){
+ sdla_te_defcfg(&card->fe_te.te_cfg);
+ }
+
+ err = sdla_setup(card->hw);
+ if (err){
+ log(LOG_INFO, "%s: Hardware setup Failed %d\n",
+ card->devname,err);
+ return -EINVAL;
+ }
+ err = sdla_intr_establish(card->hw, sdla_isr, (void*)card);
+ if (err){
+ log(LOG_INFO, "%s: Failed set interrupt handler!\n",
+ card->devname);
+ sdla_down(card->hw);
+ return -EINVAL;
+ }
+
+ switch (card->type){
+ case SDLA_AFT:
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Starting AFT Hardware Init.\n",
+ card->devname);
+#endif
+ common = wan_xilinx_init(card);
+ break;
+ }
+ if (common == NULL){
+ release_hw(card);
+ card->configured = 0;
+ return -EINVAL;
+ }
+ LIST_INSERT_HEAD(&card->dev_head, common, next);
+
+ /* Reserve I/O region and schedule background task */
+ card->critical = 0;
+ card->state = WAN_DISCONNECTED;
+ card->ioctl = wan_ioctl;
+ return 0;
+}
+
+
+/*============================================================================
+ * Shut down WAN link driver.
+ * o shut down adapter hardware
+ * o release system resources.
+ *
+ */
+#if 0
+static int shutdown (sdla_t *card)
+{
+ int err=0;
+
+ if (card->state == WAN_UNCONFIGURED){
+ return 0;
+ }
+ card->state = WAN_UNCONFIGURED;
+
+ bit_set((u_int8_t*)&card->critical, PERI_CRIT);
+
+ /* In case of piggibacking, make sure that
+ * we never try to shutdown both devices at the same
+ * time, because they depend on one another */
+
+ card->state = WAN_UNCONFIGURED;
+
+ /* Release Resources */
+ release_hw(card);
+
+ /* only free the allocated I/O range if not an S514 adapter */
+ if (!card->configured){
+ card->hw = NULL;
+ if (card->same_cpu){
+ card->same_cpu->hw = NULL;
+ card->same_cpu->same_cpu = NULL;
+ card->same_cpu=NULL;
+ }
+ }
+
+ bit_clear((u_int8_t*)&card->critical, PERI_CRIT);
+
+ return err;
+}
+#endif
+
+static void release_hw (sdla_t *card)
+{
+ log(LOG_INFO, "%s: Master shutting down\n",card->devname);
+ sdla_down(card->hw);
+ sdla_intr_disestablish(card->hw);
+ card->configured = 0;
+ return;
+}
+
+
+/****** Driver IOCTL Handlers ***********************************************/
+
+static int
+wan_ioctl(struct ifnet* ifp, int cmd, struct ifreq* ifr)
+{
+ sdla_t *card;
+ wanpipe_common_t *common = WAN_IFP_TO_COMMON(ifp);
+ int err = 0;
+
+ if (common == NULL){
+ log(LOG_INFO, "%s: Invalid softc pointer (%s:%d)!\n",
+ ifp->if_xname, __FUNCTION__, __LINE__);
+ return -EINVAL;
+ }
+ card = common->card;
+ if (card == NULL){
+ log(LOG_INFO, "%s: Card private structure corrupted (%s:%d)!\n",
+ ifp->if_xname, __FUNCTION__, __LINE__);
+ return -EINVAL;
+ }
+ switch (cmd){
+ case SIOC_WANPIPE_HWPROBE:
+ err = wan_ioctl_hwprobe(ifp, ifr->ifr_data);
+ break;
+
+ case SIOC_WANPIPE_DUMP:
+ err = wan_ioctl_dump(card, ifr->ifr_data);
+ break;
+
+ default:
+ err = 1;
+ break;
+ }
+ return err;
+}
+
+
+static int wan_ioctl_hwprobe(struct ifnet* ifp, void* u_def)
+{
+ sdla_t* card = NULL;
+ wanlite_def_t def;
+ unsigned char* str;
+ int err;
+
+ card = ((wanpipe_common_t*)ifp->if_softc)->card;
+ memset(&def, 0, sizeof(wanlite_def_t));
+ sdla_get_hwprobe(card->hw, (void**)&str);
+ if (err){
+ return -EINVAL;
+ }
+ str[strlen(str)] = '\0';
+ memcpy(def.hwprobe, str, strlen(str));
+ /* Get interface configuration */
+ if (IS_TE1(&card->fe_te.te_cfg)){
+ if (IS_T1(&card->fe_te.te_cfg)){
+ def.iface = IF_IFACE_T1;
+ }else{
+ def.iface = IF_IFACE_E1;
+ }
+ memcpy(&def.te_cfg, &card->fe_te.te_cfg, sizeof(sdla_te_cfg_t));
+ }
+
+ err = copyout(&def, u_def, sizeof(def));
+ if (err){
+ log(LOG_INFO, "%s: Failed to copy to user space (%d)\n",
+ card->devname, __LINE__);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int wan_ioctl_dump(sdla_t* card, void* u_dump)
+{
+ sdla_dump_t dump;
+ void* data;
+ u_int32_t memory;
+ int err = 0;
+
+ err = copyin(u_dump, &dump, sizeof(sdla_dump_t));
+ if (err){
+ return -EFAULT;
+ }
+
+ sdla_getcfg(card->hw, SDLA_MEMORY, &memory);
+ if (dump.magic != WANPIPE_MAGIC){
+ return -EINVAL;
+ }
+
+ if ((dump.offset + dump.length) > memory){
+ return -EINVAL;
+ }
+
+ data = malloc(dump.length, M_DEVBUF, M_NOWAIT);
+ if (data == NULL){
+ return -ENOMEM;
+ }
+
+ sdla_peek(card->hw, dump.offset, data, dump.length);
+ err = copyout(data, dump.ptr, dump.length);
+ if (err){
+ log(LOG_INFO, "%s: Failed to copy to user space (%d)\n",
+ card->devname, __LINE__);
+ err = -EFAULT;
+ }
+ free(data, M_DEVBUF);
+ return err;
+}
+
+/******* Miscellaneous ******************************************************/
+
+/*============================================================================
+ * SDLA Interrupt Service Routine.
+ * o call protocol-specific interrupt service routine, if any.
+ */
+int sdla_isr (void* pcard)
+{
+ sdla_t *card = (sdla_t*)pcard;
+
+ if (card == NULL || card->magic != WANPIPE_MAGIC) return 0;
+
+ switch (card->type){
+ case SDLA_AFT:
+ if (card->isr){
+ card->isr(card);
+ }
+ break;
+ }
+ return 1;
+}
+
+struct mbuf* wan_mbuf_alloc(void)
+{
+ struct mbuf *m;
+
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m != NULL){
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0){
+ m_freem(m);
+ m = NULL;
+ }
+ }
+ return m;
+}
+
+/****** End *********************************************************/
diff --git a/sys/dev/pci/if_san_common.h b/sys/dev/pci/if_san_common.h
new file mode 100644
index 00000000000..fee5af695f3
--- /dev/null
+++ b/sys/dev/pci/if_san_common.h
@@ -0,0 +1,400 @@
+/*-
+ * Copyright (c) 2001-2004 Sangoma Technologies (SAN)
+ * All rights reserved. www.sangoma.com
+ *
+ * This code is written by Alex Feldman <al.feldman@sangoma.com> for SAN.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sangoma Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SANGOMA TECHNOLOGIES AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __IF_SAN_COMMON_H
+#define __IF_SAN_COMMON_H
+
+# include <dev/pci/if_san_te1.h>
+# include <dev/pci/if_sandrv.h>
+
+#define WANPIPE_LITE_VERSION "1.1.1"
+#define WAN_OPENBSD_PLATFORM 0x06
+#define WAN_PLATFORM_ID WAN_OPENBSD_PLATFORM
+#define WANPIPE_MAGIC 0x414C4453L /* signature: 'SDLA' reversed */
+
+#define ROUTER_NAME "wanrouter" /* in case we ever change it */
+#define ROUTER_IOCTL 'W' /* for IOCTL calls */
+
+#define WANROUTER_MAJOR_VER 2
+#define WANROUTER_MINOR_VER 1
+
+/* IOCTL codes for /proc/router/<device> entries (up to 255) */
+# define WANPIPE_DUMP _IOW(ROUTER_IOCTL, 16, wan_conf_t)
+# define WANPIPE_EXEC _IOWR(ROUTER_IOCTL, 17, wan_conf_t)
+# define SIOC_WANPIPE_PIPEMON _IOWR('i', 150, struct ifreq) /* get monitor statistics */
+# define SIOC_WANPIPE_DEVICE _IOWR('i', 151, struct ifreq) /* set generic device */
+# define SIOC_WANPIPE_HWPROBE _IOWR('i', 152, struct ifreq) /* get hwprobe string */
+# define SIOC_WANPIPE_DUMP _IOWR('i', 153, struct ifreq) /* get memdump string (GENERIC) */
+
+/* clocking options */
+#define WANOPT_EXTERNAL 0
+#define WANOPT_INTERNAL 1
+
+/* intercace options */
+#define WANOPT_RS232 0
+#define WANOPT_V35 1
+
+#define WAN_UDP_FAILED_CMD 0xCF
+#define WAN_UDP_INVALID_CMD 0xCE
+#define WAN_UDP_TIMEOUT_CMD 0xAA
+#define WAN_UDP_INVALID_NET_CMD 0xCD
+
+#define WANOPT_NO 0
+#define WANOPT_YES 1
+
+/* UDP Packet Management */
+#define UDP_PKT_FRM_STACK 0x00
+#define UDP_PKT_FRM_NETWORK 0x01
+
+#define WANCONFIG_FR 102 /* frame relay link */
+#define WANCONFIG_PPP 103 /* synchronous PPP link */
+#define WANCONFIG_CHDLC 104 /* Cisco HDLC Link */
+#define WANCONFIG_AFT 117 /* AFT Hardware Support */
+/****** Data Types **********************************************************/
+
+
+/* Front-End status */
+enum fe_status {
+ FE_UNITIALIZED = 0x00,
+ FE_DISCONNECTED,
+ FE_CONNECTED
+};
+
+/* 'state' defines */
+enum wan_states
+{
+ WAN_UNCONFIGURED, /* link/channel is not configured */
+ WAN_DISCONNECTED, /* link/channel is disconnected */
+ WAN_CONNECTING, /* connection is in progress */
+ WAN_CONNECTED, /* link/channel is operational */
+ WAN_LIMIT, /* for verification only */
+ WAN_DUALPORT, /* for Dual Port cards */
+ WAN_DISCONNECTING,
+ WAN_FT1_READY /* FT1 Configurator Ready */
+};
+
+/* 'modem_status' masks */
+#define WAN_MODEM_CTS 0x0001 /* CTS line active */
+#define WAN_MODEM_DCD 0x0002 /* DCD line active */
+#define WAN_MODEM_DTR 0x0010 /* DTR line active */
+#define WAN_MODEM_RTS 0x0020 /* RTS line active */
+
+typedef struct wan_conf
+{
+ char devname[IFNAMSIZ+1];
+ void* arg;
+} wan_conf_t;
+
+
+/* IOCTL numbers (up to 16) */
+
+#define TRACE_ALL 0x00
+#define TRACE_PROT 0x01
+#define TRACE_DATA 0x02
+
+/* values for request/reply byte */
+#define UDPMGMT_REQUEST 0x01
+#define UDPMGMT_REPLY 0x02
+#define UDP_OFFSET 12
+
+#define MAX_FT1_RETRY 100
+
+/* General Critical Flags */
+enum {
+ SEND_CRIT,
+ PERI_CRIT,
+ RX_CRIT,
+ PRIV_CRIT
+};
+
+/*
+ * Data structures for IOCTL calls.
+ */
+
+typedef struct sdla_dump /* WANPIPE_DUMP */
+{
+ unsigned long magic; /* for verification */
+ unsigned long offset; /* absolute adapter memory address */
+ unsigned long length; /* block length */
+ void* ptr; /* -> buffer */
+} sdla_dump_t;
+
+typedef struct sdla_exec /* WANPIPE_EXEC */
+{
+ unsigned long magic; /* for verification */
+ void* cmd; /* -> command structure */
+ void* data; /* -> data buffer */
+} sdla_exec_t;
+
+#define TRC_INCOMING_FRM 0x00
+#define TRC_OUTGOING_FRM 0x01
+typedef struct
+{
+ unsigned char status;
+ unsigned char data_avail;
+ unsigned short real_length;
+ unsigned short time_stamp;
+ unsigned long sec;
+ unsigned long usec;
+ unsigned char data[0];
+} wan_trace_pkt_t;
+
+typedef struct wan_trace
+{
+ unsigned long tracing_enabled;
+ struct ifqueue ifq;
+ unsigned int trace_timeout;
+ unsigned int max_trace_queue;
+} wan_trace_t;
+
+
+/********************************************************
+ * GLOBAL DEFINITION FOR SANGOMA UDP STRUCTURE *
+ *******************************************************/
+#define GLOBAL_UDP_SIGNATURE "WANPIPE"
+#define GLOBAL_UDP_SIGNATURE_LEN 7
+#define UDPMGMT_UDP_PROTOCOL 0x11
+#define WAN_UDP_CMD_START 0x60
+#define WAN_GET_PROTOCOL (WAN_UDP_CMD_START+0)
+#define WAN_GET_PLATFORM (WAN_UDP_CMD_START+1)
+#define WAN_GET_MEDIA_TYPE (WAN_UDP_CMD_START+2)
+#define WAN_UDP_CMD_END 0x6F
+
+#define WAN_FE_CMD_START 0x90
+#define WAN_FE_CMD_END 0x9F
+
+#define WAN_INTERFACE_CMD_START 0xA0
+#define WAN_INTERFACE_CMD_END 0xAF
+
+#define WAN_FE_UDP_CMD_START 0xB0
+#define WAN_FE_UDP_CMD_END 0xBF
+
+typedef struct {
+ unsigned char signature[8];
+ unsigned char request_reply;
+ unsigned char id;
+ unsigned char reserved[6];
+} wan_mgmt_t;
+
+
+/****** DEFINITION OF UDP HEADER AND STRUCTURE PER PROTOCOL ******/
+typedef struct {
+ unsigned char num_frames;
+ unsigned char ismoredata;
+} wan_trace_info_t;
+
+typedef struct wan_udp_hdr{
+ wan_mgmt_t wan_mgmt;
+ wan_cmd_t wan_cmd;
+ union {
+ struct {
+ wan_trace_info_t trace_info;
+ unsigned char data[WAN_MAX_DATA_SIZE];
+ } chdlc, aft;
+ unsigned char data[WAN_MAX_DATA_SIZE];
+ } wan_udphdr_u;
+#define wan_udphdr_signature wan_mgmt.signature
+#define wan_udphdr_request_reply wan_mgmt.request_reply
+#define wan_udphdr_id wan_mgmt.id
+#define wan_udphdr_opp_flag wan_cmd.wan_cmd_opp_flag
+#define wan_udphdr_command wan_cmd.wan_cmd_command
+#define wan_udphdr_data_len wan_cmd.wan_cmd_data_len
+#define wan_udphdr_return_code wan_cmd.wan_cmd_return_code
+#define wan_udphdr_chdlc_num_frames wan_udphdr_u.chdlc.trace_info.num_frames
+#define wan_udphdr_chdlc_ismoredata wan_udphdr_u.chdlc.trace_info.ismoredata
+#define wan_udphdr_chdlc_data wan_udphdr_u.chdlc.data
+
+#define wan_udphdr_aft_num_frames wan_udphdr_u.aft.trace_info.num_frames
+#define wan_udphdr_aft_ismoredata wan_udphdr_u.aft.trace_info.ismoredata
+#define wan_udphdr_aft_data wan_udphdr_u.aft.data
+#define wan_udphdr_data wan_udphdr_u.data
+} wan_udp_hdr_t;
+
+#define MAX_LGTH_UDP_MGNT_PKT 2000
+
+/* This is used for interrupt testing */
+#define INTR_TEST_MODE 0x02
+
+#define WUM_SIGNATURE_L 0x50495046
+#define WUM_SIGNATURE_H 0x444E3845
+
+#define WUM_KILL 0x50
+#define WUM_EXEC 0x51
+
+
+#if defined(_KERNEL)
+/****** Kernel Interface ****************************************************/
+
+
+#define MAX_E1_CHANNELS 32
+#define MAX_FR_CHANNELS (991+1)
+
+#ifndef min
+#define min(a,b) (((a)<(b))?(a):(b))
+#endif
+#ifndef max
+#define max(a,b) (((a)>(b))?(a):(b))
+#endif
+
+#define is_digit(ch) (((ch)>=(unsigned)'0'&&(ch)<=(unsigned)'9')?1:0)
+#define is_alpha(ch) ((((ch)>=(unsigned)'a'&&(ch)<=(unsigned)'z')||\
+ ((ch)>=(unsigned)'A'&&(ch)<=(unsigned)'Z'))?1:0)
+#define is_hex_digit(ch) ((((ch)>=(unsigned)'0'&&(ch)<=(unsigned)'9')||\
+ ((ch)>=(unsigned)'a'&&(ch)<=(unsigned)'f')||\
+ ((ch)>=(unsigned)'A'&&(ch)<=(unsigned)'F'))?1:0)
+#if !defined(offsetof)
+# define offsetof(type, member) ((size_t)(&((type*)0)->member))
+#endif
+
+# define irqreturn_t void
+/* Unsafe sprintf and vsprintf function removed from the kernel */
+# define WAN_IRQ_RETVAL(a) return;
+
+/****** Data Structures *****************************************************/
+
+typedef struct wan_udp_pkt {
+ struct ip ip_hdr;
+ struct udphdr udp_hdr;
+ wan_udp_hdr_t wan_udp_hdr;
+#define wan_udp_cmd wan_udp_hdr.wan_cmd
+#define wan_udp_signature wan_udp_hdr.wan_udphdr_signature
+#define wan_udp_request_reply wan_udp_hdr.wan_udphdr_request_reply
+#define wan_udp_id wan_udp_hdr.wan_udphdr_id
+#define wan_udp_opp_flag wan_udp_hdr.wan_udphdr_opp_flag
+#define wan_udp_command wan_udp_hdr.wan_udphdr_command
+#define wan_udp_data_len wan_udp_hdr.wan_udphdr_data_len
+#define wan_udp_return_code wan_udp_hdr.wan_udphdr_return_code
+#define wan_udp_hdlc_PF_bit wan_udp_hdr.wan_udphdr_hdlc_PF_bit
+#define wan_udp_fr_dlci wan_udp_hdr.wan_udphdr_fr_dlci
+#define wan_udp_fr_attr wan_udp_hdr.wan_udphdr_fr_attr
+#define wan_udp_fr_rxlost1 wan_udp_hdr.wan_udphdr_fr_rxlost1
+#define wan_udp_fr_rxlost2 wan_udp_hdr.wan_udphdr_fr_rxlost2
+#define wan_udp_chdlc_num_frames wan_udp_hdr.wan_udphdr_chdlc_num_frames
+#define wan_udp_chdlc_ismoredata wan_udp_hdr.wan_udphdr_chdlc_ismoredata
+#define wan_udp_chdlc_data wan_udp_hdr.wan_udphdr_chdlc_data
+
+#define wan_udp_aft_num_frames wan_udp_hdr.wan_udphdr_aft_num_frames
+#define wan_udp_aft_ismoredata wan_udp_hdr.wan_udphdr_aft_ismoredata
+#define wan_udp_data wan_udp_hdr.wan_udphdr_data
+} wan_udp_pkt_t;
+
+#define WAN_IFP_TO_COMMON(ifp) (wanpipe_common_t*)((ifp)->if_softc)
+typedef struct wanpipe_common
+{
+ struct sppp ifp;
+ void *card;
+ struct timeout dev_timer;
+ unsigned int protocol;
+ struct ifmedia ifm;
+
+ LIST_ENTRY(wanpipe_common) next;
+} wanpipe_common_t;
+
+typedef struct
+{
+ unsigned long time_slot_map;
+ unsigned long logic_ch_map;
+ unsigned char num_of_time_slots;
+ unsigned char top_logic_ch;
+ unsigned long bar;
+ void *trace_info;
+ void *dev_to_ch_map[MAX_E1_CHANNELS];
+ void *rx_dma_ptr;
+ void *tx_dma_ptr;
+ unsigned short num_of_ch;/* Number of logical channels */
+ unsigned short dma_per_ch;/* DMA buffers per logic channel */
+ unsigned short mru_trans;/* MRU of transparent channels */
+ unsigned long dma_mtu_off;
+ unsigned short dma_mtu;
+ unsigned char state_change_exit_isr;
+ unsigned long active_ch_map;
+ unsigned long fifo_addr_map;
+ struct timeout led_timer;
+} sdla_xilinx_t;
+
+/* Adapter Data Space.
+ * This structure is needed because we handle multiple cards, otherwise
+ * static data would do it.
+ */
+typedef struct sdla
+{
+ unsigned magic;
+ char devname[IFNAMSIZ+1]; /* card name */
+ void *hw; /* hw configuration */
+ unsigned int type; /* adapter type */
+ unsigned char line_idle;
+
+ char state; /* device state */
+ unsigned long critical; /* critical section flag */
+
+ int (*iface_up) (struct ifnet*);
+ int (*iface_down) (struct ifnet*);
+ int (*iface_send) (struct mbuf* skb, struct ifnet*);
+ int (*iface_ioctl) (struct ifnet*, int, struct ifreq*);
+
+ unsigned long state_tick; /* link state timestamp */
+ unsigned long in_isr; /* interrupt-in-service flag */
+ unsigned long configured; /* configurations status */
+ int (*del_if) (struct sdla*, struct ifnet*);
+ void (*isr)(struct sdla*); /* interrupt service routine */
+ void (*poll)(struct sdla*); /* polling routine */
+ int (*exec)(struct sdla*, void*, void*);
+ int (*ioctl) (struct ifnet*, int, struct ifreq*);
+
+ union
+ {
+ sdla_xilinx_t xilinx;
+ } u;
+
+ sdla_fe_iface_t fe_iface;
+ union {
+#define fe_te u_fe.te_sc
+ sdla_te_softc_t te_sc;
+ } u_fe;
+
+ unsigned char front_end_status;
+ WRITE_FRONT_END_REG_T* write_front_end_reg;
+ READ_FRONT_END_REG_T* read_front_end_reg;
+ void (*te_enable_timer) (void*);
+ void (*te_link_state) (void*);
+
+ LIST_HEAD(,wanpipe_common) dev_head;
+ LIST_ENTRY(sdla) next; /* -> next device */
+} sdla_t;
+
+/****** Public Functions ****************************************************/
+
+void* wan_xilinx_init(sdla_t*); /* Xilinx Hardware Support */
+struct mbuf* wan_mbuf_alloc(void);
+
+#endif /* __KERNEL__ */
+#endif /* __IF_SAN_COMMON_H */
diff --git a/sys/dev/pci/if_san_front_end.h b/sys/dev/pci/if_san_front_end.h
new file mode 100644
index 00000000000..7956f9631c0
--- /dev/null
+++ b/sys/dev/pci/if_san_front_end.h
@@ -0,0 +1,217 @@
+/*-
+ * Copyright (c) 2001-2004 Sangoma Technologies (SAN)
+ * All rights reserved. www.sangoma.com
+ *
+ * This code is written by Alex Feldman <al.feldman@sangoma.com> for SAN.
+ * The code is derived from permitted modifications to software created
+ * by Nenad Corbic (ncorbic@sangoma.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sangoma Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SANGOMA TECHNOLOGIES AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __IF_SAN_FRONT_END_H_
+#define __IF_SAN_FRONT_END_H_
+
+/*
+*************************************************************************
+* DEFINES AND MACROS *
+*************************************************************************
+*/
+/* The hardware media */
+#define WANOPT_MEDIA_NONE 0x00 /* Regular card */
+#define WANOPT_MEDIA_T1 0x01 /* T1 connection */
+#define WANOPT_MEDIA_E1 0x02 /* E1 connection */
+#define WANOPT_MEDIA_56K 0x03 /* 56K connection */
+
+/* settings for the 'adapter_type' */
+#define S508_ADPTR 0x0001 /* S508 */
+#define S5141_ADPTR_1_CPU_SERIAL 0x0011 /* S5141, single CPU, serial */
+#define S5142_ADPTR_2_CPU_SERIAL 0x0012 /* S5142, dual CPU, serial */
+#define S5143_ADPTR_1_CPU_FT1 0x0013 /* S5143, single CPU, FT1 */
+#define S5144_ADPTR_1_CPU_T1E1 0x0014 /* S5144, single CPU, T1/E1 */
+#define S5145_ADPTR_1_CPU_56K 0x0015 /* S5145, single CPU, 56K */
+#define S5147_ADPTR_2_CPU_T1E1 0x0017 /* S5147, dual CPU, T1/E1 */
+#define S5148_ADPTR_1_CPU_T1E1 0x0018 /* S5148, single CPU, T1/E1 */
+
+#define S518_ADPTR_1_CPU_ADSL 0x0018 /* S518, adsl card */
+
+#define A101_ADPTR_T1E1_MASK 0x0040 /* T1/E1 type mask */
+#define A101_ADPTR_1TE1 0x0041 /* 1 Channel T1/E1 */
+#define A101_ADPTR_2TE1 0x0042 /* 2 Channels T1/E1 */
+
+#define A100_ADPTR_T3E3_MASK 0x0080 /* T3/E3 type mask */
+#define A100_ADPTR_1_CHN_T3E3 0x0081 /* 1 Channel T3/E3 (Prototype) */
+#define A105_ADPTR_1_CHN_T3E3 0x0082 /* 1 Channel T3/E3 */
+
+#define OPERATE_T1E1_AS_SERIAL 0x8000 /* For bitstreaming only
+ * Allow the applicatoin to
+ * E1 front end */
+
+#define SDLA_ADPTR_DECODE(adapter_type) \
+ (adapter_type == S5141_ADPTR_1_CPU_SERIAL) ? "S514-1-PCI" : \
+ (adapter_type == S5142_ADPTR_2_CPU_SERIAL) ? "S514-2-PCI" : \
+ (adapter_type == S5143_ADPTR_1_CPU_FT1) ? "S514-3-PCI" : \
+ (adapter_type == S5144_ADPTR_1_CPU_T1E1) ? "S514-4-PCI" : \
+ (adapter_type == S5145_ADPTR_1_CPU_56K) ? "S514-5-PCI" : \
+ (adapter_type == S5147_ADPTR_2_CPU_T1E1) ? "S514-7-PCI" : \
+ (adapter_type == S518_ADPTR_1_CPU_ADSL) ? "S518-PCI " : \
+ (adapter_type == A101_ADPTR_1TE1) ? "AFT-A101 " : \
+ (adapter_type == A101_ADPTR_2TE1) ? "AFT-A102 " : \
+ (adapter_type == A105_ADPTR_1_CHN_T3E3) ? "A105-1-PCI" : \
+ (adapter_type == A105_ADPTR_1_CHN_T3E3) ? "A105-2 " : \
+ "UNKNOWN "
+
+/* front-end UDP command */
+#define WAN_FE_GET_STAT (WAN_FE_UDP_CMD_START + 0)
+#define WAN_FE_SET_LB_MODE (WAN_FE_UDP_CMD_START + 1)
+#define WAN_FE_FLUSH_PMON (WAN_FE_UDP_CMD_START + 2)
+#define WAN_FE_GET_CFG (WAN_FE_UDP_CMD_START + 3)
+
+/* front-end configuration and access interface commands */
+#define READ_FRONT_END_REGISTER (WAN_FE_CMD_START+0) /* 0x90 read from front-end register */
+#define WRITE_FRONT_END_REGISTER (WAN_FE_CMD_START+1) /* 0x91 write to front-end register */
+#define READ_FRONT_END_STATISTICS (WAN_FE_CMD_START+2) /* 0x92 read the front-end statistics */
+#define FLUSH_FRONT_END_STATISTICS (WAN_FE_CMD_START+3) /* 0x93 flush the front-end statistics */
+
+#ifdef _KERNEL
+
+/* adapter configuration interface commands */
+#define SET_ADAPTER_CONFIGURATION (WAN_INTERFACE_CMD_START+0) /* 0xA0 set adapter configuration */
+#define READ_ADAPTER_CONFIGURATION (WAN_INTERFACE_CMD_START+1) /* 0xA1 read adapter configuration */
+
+/* front-end command */
+#define WAN_FE_GET_STAT (WAN_FE_UDP_CMD_START + 0)
+#define WAN_FE_SET_LB_MODE (WAN_FE_UDP_CMD_START + 1)
+#define WAN_FE_FLUSH_PMON (WAN_FE_UDP_CMD_START + 2)
+#define WAN_FE_GET_CFG (WAN_FE_UDP_CMD_START + 3)
+
+/* return codes from interface commands */
+#define LGTH_FE_CFG_DATA_INVALID 0x91 /* the length of the FE_RX_DISC_TX_IDLE_STRUCT is invalid */
+#define LGTH_ADAPTER_CFG_DATA_INVALID 0x91 /* the length of the passed configuration data is invalid */
+#define INVALID_FE_CFG_DATA 0x92 /* the passed SET_FE_RX_DISC_TX_IDLE_CFG data is invalid */
+#define ADPTR_OPERATING_FREQ_INVALID 0x92 /* an invalid adapter operating frequency was selected */
+#define PROT_CFG_BEFORE_FE_CFG 0x93 /* set the protocol-level configuration before setting the FE configuration */
+
+#define SET_FE_RX_DISC_TX_IDLE_CFG 0x98 /* set the front-end Rx discard/Tx idle configuration */
+#define READ_FE_RX_DISC_TX_IDLE_CFG 0x99 /* read the front-end Rx discard/Tx idle configuration */
+#define SET_TE1_SIGNALING_CFG 0x9A /* set the T1/E1 signaling configuration */
+#define READ_TE1_SIGNALING_CFG 0x9B /* read the T1/E1 signaling configuration */
+
+
+#define COMMAND_INVALID_FOR_ADAPTER 0x9F /* the command is invalid for the adapter type */
+
+
+/* ---------------------------------------------------------------------------------
+ * Constants for the SET_FE_RX_DISC_TX_IDLE_CFG/READ_FE_RX_DISC_TX_IDLE_CFG commands
+ * --------------------------------------------------------------------------------*/
+
+#define NO_ACTIVE_RX_TIME_SLOTS_T1 24 /* T1 - no active time slots used for reception */
+#define NO_ACTIVE_TX_TIME_SLOTS_T1 24 /* T1 - no active time slots used for transmission */
+#define NO_ACTIVE_RX_TIME_SLOTS_E1 32 /* E1 - no active time slots used for reception */
+#define NO_ACTIVE_TX_TIME_SLOTS_E1 31 /* E1 - no active time slots used for transmission (channel 0 reserved for framing) */
+
+/* Read/Write to front-end register */
+#define READ_REG(reg) card->read_front_end_reg(card, reg)
+#define WRITE_REG(reg, value) card->write_front_end_reg(card, reg, (unsigned char)(value))
+
+/* the structure used for the SET_FE_RX_DISC_TX_IDLE_CFG/READ_FE_RX_DISC_TX_IDLE_CFG command */
+#pragma pack(1)
+typedef struct {
+ unsigned short lgth_Rx_disc_bfr; /* the length of the Rx discard buffer */
+ unsigned short lgth_Tx_idle_bfr; /* the length of the Tx idle buffer */
+ /* the transmit idle data buffer */
+ unsigned char Tx_idle_data_bfr[NO_ACTIVE_TX_TIME_SLOTS_E1];
+} FE_RX_DISC_TX_IDLE_STRUCT;
+#pragma pack()
+
+
+/* ----------------------------------------------------------------------------
+ * Constants for front-end access
+ * --------------------------------------------------------------------------*/
+
+/* the structure used for the READ_FRONT_END_REGISTER/WRITE_FRONT_END_REGISTER command */
+#pragma pack(1)
+typedef struct {
+ unsigned short register_number; /* the register number to be read from or written to */
+ unsigned char register_value; /* the register value read/written */
+} FRONT_END_REG_STRUCT;
+#pragma pack()
+
+
+/* -----------------------------------------------------------------------------
+ * Constants for the READ_FRONT_END_STATISTICS command
+ * ---------------------------------------------------------------------------*/
+
+/* the front-end statistics structure */
+#pragma pack(1)
+typedef struct {
+ unsigned long FE_interrupt_count; /* the number of front-end interrupts generated */
+ unsigned long FE_app_timeout_count; /* the number of front-end interrupt application timeouts */
+} FE_STATISTICS_STRUCT;
+#pragma pack()
+
+
+
+/* --------------------------------------------------------------------------------
+ * Constants for the SET_ADAPTER_CONFIGURATION/READ_ADAPTER_CONFIGURATION commands
+ * -------------------------------------------------------------------------------*/
+
+/* the adapter configuration structure */
+#pragma pack(1)
+typedef struct {
+ unsigned short adapter_type; /* type of adapter */
+ unsigned short adapter_config; /* miscellaneous adapter configuration options */
+ unsigned long operating_frequency; /* adapter operating frequency */
+} ADAPTER_CONFIGURATION_STRUCT;
+#pragma pack()
+
+
+
+typedef unsigned char (WRITE_FRONT_END_REG_T)(void*, unsigned short, unsigned char);
+typedef unsigned char (READ_FRONT_END_REG_T)(void*, unsigned short);
+
+
+enum {
+ AFT_LED_ON,
+ AFT_LED_OFF,
+ AFT_LED_TOGGLE
+};
+
+
+/*
+** Sangoma Front-End interface structure
+*/
+typedef struct {
+ unsigned long (*get_fe_service_status)(void*); /* In-Service or Not (T1/E1/56K) */
+ void (*print_fe_alarm)(void*,unsigned long); /* Print Front-End alarm (T1/E1/56K) */
+ char* (*print_fe_act_channels)(void*); /* Print Front-End alarm (T1/E1/56K) */
+ void (*set_fe_alarm)(void*,unsigned long); /* Set Front-End alarm (T1/E1) */
+} sdla_fe_iface_t;
+
+
+#endif /* _KERNEL */
+
+#endif
diff --git a/sys/dev/pci/if_san_obsd.c b/sys/dev/pci/if_san_obsd.c
new file mode 100644
index 00000000000..1744a275ddf
--- /dev/null
+++ b/sys/dev/pci/if_san_obsd.c
@@ -0,0 +1,393 @@
+/*-
+ * Copyright (c) 2001-2004 Sangoma Technologies (SAN)
+ * All rights reserved. www.sangoma.com
+ *
+ * This code is written by Alex Feldman <al.feldman@sangoma.com> for SAN.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sangoma Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SANGOMA TECHNOLOGIES AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+# include </usr/include/bitstring.h>
+# include <sys/types.h>
+# include <sys/param.h>
+# include <sys/systm.h>
+# include <sys/syslog.h>
+# include <sys/ioccom.h>
+# include <sys/conf.h>
+# include <sys/malloc.h>
+# include <sys/errno.h>
+# include <sys/exec.h>
+# include <sys/mbuf.h>
+# include <sys/sockio.h>
+# include <sys/socket.h>
+# include <sys/kernel.h>
+# include <sys/device.h>
+# include <sys/time.h>
+# include <sys/timeout.h>
+
+# include <net/if.h>
+# include <net/if_media.h>
+# include <net/netisr.h>
+# include <net/if_sppp.h>
+# include <netinet/in_systm.h>
+# include <netinet/in.h>
+
+# include <netinet/udp.h>
+# include <netinet/ip.h>
+
+#include <dev/pci/if_san_common.h>
+#include <dev/pci/if_san_obsd.h>
+
+/****** Defines & Macros ****************************************************/
+
+#ifdef _DEBUG_
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+/****** Function Prototypes *************************************************/
+
+static sdla_t* wanpipe_generic_getcard(struct ifnet*);
+static int wanpipe_generic_ioctl(struct ifnet*, u_long, caddr_t);
+static void wanpipe_generic_watchdog(struct ifnet*);
+static void wanpipe_generic_start(struct ifnet*);
+
+/****** Global Data **********************************************************
+ * Note: All data must be explicitly initialized!!!
+ */
+static char* san_ifname_format = "san%d";
+
+/******* WAN Device Driver Entry Points *************************************/
+static sdla_t* wanpipe_generic_getcard(struct ifnet* ifp)
+{
+ sdla_t* card;
+
+ if (ifp->if_softc == NULL){
+ log(LOG_INFO, "%s: Invalid device private structure pointer\n",
+ ifp->if_xname);
+ return NULL;
+ }
+ card = ((sdla_t*)((wanpipe_common_t*)ifp->if_softc)->card);
+ if (card == NULL){
+ log(LOG_INFO, "%s: Invalid Sangoma device card\n",
+ ifp->if_xname);
+ return NULL;
+ }
+ return card;
+}
+
+int wanpipe_generic_name(sdla_t* card, char* ifname)
+{
+ static int ifunit = 0;
+#if 0
+ char if_name[IFNAMSIZ+1];
+
+ snprintf(if_name, strlen(if_name), ifname_format, ifunit++);
+ bcopy(if_name, ifname, strlen(if_name));
+#endif
+ snprintf(ifname, IFNAMSIZ+1, san_ifname_format, ifunit++);
+ return 0;
+}
+
+int wanpipe_generic_register (sdla_t* card, struct ifnet* ifp, char *ifname)
+{
+ if (ifname == NULL || strlen(ifname) > IFNAMSIZ){
+ return -EINVAL;
+ }else{
+ bcopy(ifname, ifp->if_xname, strlen(ifname));
+ }
+ IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ ifp->if_mtu = PP_MTU;
+ ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
+ ((struct sppp *)ifp)->pp_flags |= PP_CISCO;
+ ((struct sppp *)ifp)->pp_flags |= PP_KEEPALIVE;
+ ifp->if_ioctl = wanpipe_generic_ioctl; /* Will set from new_if() */
+ ifp->if_start = wanpipe_generic_start;
+ ifp->if_watchdog = wanpipe_generic_watchdog;
+
+ if_attach(ifp);
+ if_alloc_sadl(ifp);
+ sppp_attach(ifp);
+#if defined(NBPFILTER)
+ bpfattach(&ifp->if_bpf, ifp, DLT_NULL, 4);
+#endif
+ return 0;
+}
+
+void wanpipe_generic_unregister (struct ifnet* ifp)
+{
+ log(LOG_INFO, "%s: Unregister interface!\n",
+ ifp->if_xname);
+ sppp_detach(ifp);
+ if_free_sadl(ifp);
+ if_detach(ifp);
+}
+
+
+static void wanpipe_generic_start(struct ifnet* ifp)
+{
+ sdla_t* card;
+ struct mbuf *opkt;
+ int err = 0;
+#if defined(NBPFILTER)
+ struct mbuf m0;
+ u_int32_t af = AF_INET;
+#endif
+
+ if ((card = wanpipe_generic_getcard(ifp)) == NULL){
+ return;
+ }
+ while (1){
+ if (sppp_isempty(ifp)){
+ /* No more packets in send queue */
+ break;
+ }
+
+ if ((opkt = sppp_dequeue(ifp)) == NULL){
+ /* Should never happened, packet pointer is NULL */
+ break;
+ }
+ if (card->iface_send == NULL){
+ m_freem(opkt);
+ break;
+ }
+ /* report the packet to BPF if present and attached */
+#if defined(NBPFILTER)
+ if (ifp->if_bpf){
+ m0.m_next = opkt;
+ m0.m_len = 4;
+ m0.m_data = (char*)&af;
+ bpf_mtap(ifp->if_bpf, &m0);
+ }
+#endif
+
+ err = card->iface_send(opkt, ifp);
+ if (err){
+ break;
+ }
+ }
+ return;
+}
+
+
+static int wanpipe_generic_ioctl(struct ifnet* ifp, u_long cmd, caddr_t data)
+{
+ struct ifreq *ifr = (struct ifreq*)data;
+ sdla_t *card;
+ wanpipe_common_t* common = WAN_IFP_TO_COMMON(ifp);
+ struct if_settings ifsettings;
+ unsigned long ts_map;
+ int err = 0, s;
+
+ if ((card = wanpipe_generic_getcard(ifp)) == NULL){
+ return -EINVAL;
+ }
+ s = splnet();
+ switch (cmd){
+ case SIOCSIFADDR:
+ err = 1;
+ break;
+
+ case SIOCSIFMEDIA:
+ /* You can't set new media type while card is running */
+ if (card->state != WAN_DISCONNECTED){
+ log(LOG_INFO, "%s: Unable to change media type!\n",
+ ifp->if_xname);
+ err = -EINVAL;
+ goto ioctl_out;
+ }
+ err = ifmedia_ioctl(ifp, ifr, &common->ifm, cmd);
+ break;
+
+ case SIOCGIFMEDIA:
+ err = ifmedia_ioctl(ifp, ifr, &common->ifm, cmd);
+ break;
+
+ case SIOCSIFTIMESLOT:
+ if (card->state != WAN_DISCONNECTED){
+ log(LOG_INFO, "%s: Unable to change timeslot map!\n",
+ ifp->if_xname);
+ err = -EINVAL;
+ goto ioctl_out;
+ }
+ err = copyin(ifr->ifr_data, &ts_map, sizeof(ts_map));
+ if (err)
+ goto ioctl_out;
+ sdla_te_settimeslot(card, ts_map);
+ break;
+
+ case SIOCGIFTIMESLOT:
+ ts_map = sdla_te_gettimeslot(card);
+ err = copyout(ifr->ifr_data, &ts_map, sizeof(ts_map));
+ if (err)
+ goto ioctl_out;
+ break;
+
+ case SIOCSIFFLAGS:
+ /*
+ ** If the interface is marked up - enable communications.
+ ** If down - disable communications. IFF_UP is taken
+ ** care of before entering this function.
+ */
+ if ((ifp->if_flags & IFF_UP) == 0){
+ /* bring it down */
+ log(LOG_INFO, "%s: Bringing interface down.\n",
+ ifp->if_xname);
+ if (card->iface_down){
+ card->iface_down(ifp);
+ }
+ }else{ /* bring it up */
+ log(LOG_INFO, "%s: Bringing interface up.\n",
+ ifp->if_xname);
+ if (card->iface_up){
+ card->iface_up(ifp);
+ }
+ wanpipe_generic_start(ifp);
+ }
+ break;
+
+ case SIOC_WANPIPE_DEVICE:
+ err = copyin(ifr->ifr_data,
+ &ifsettings,
+ sizeof(struct if_settings));
+ if (err){
+ log(LOG_INFO, "%s: Failed to copy from user space!\n",
+ card->devname);
+ goto ioctl_out;
+ }
+ switch (ifsettings.type){
+ case IF_GET_PROTO:
+ ifsettings.type = common->protocol;
+ err = copyout(&ifsettings,
+ ifr->ifr_data,
+ sizeof(struct if_settings));
+ if (err){
+ log(LOG_INFO, "%s: Failed to copy to uspace!\n",
+ card->devname);
+ }
+ break;
+
+ case IF_PROTO_CISCO:
+ case IF_PROTO_PPP:
+ err = wp_lite_set_proto(ifp, (struct ifreq*)data);
+ break;
+
+ default:
+ if (card->iface_ioctl){
+ err = card->iface_ioctl(
+ ifp,
+ cmd,
+ (struct ifreq*)data);
+ }
+ break;
+ }
+ break;
+
+ default:
+ if (card->iface_ioctl){
+ /* Argument seqeunce is change for Linux order */
+ err = card->iface_ioctl(ifp, cmd, (struct ifreq*)data);
+ }
+ break;
+ }
+
+ if (err){
+ err = sppp_ioctl(ifp, cmd, data);
+ }
+ioctl_out:
+ splx(s);
+ return err;
+}
+
+static void wanpipe_generic_watchdog(struct ifnet* ifp)
+{
+ return;
+}
+
+int wanpipe_generic_open(struct ifnet* ifp)
+{
+ return 0;
+}
+
+int wanpipe_generic_close(struct ifnet* ifp)
+{
+ return 0;
+}
+
+int wanpipe_generic_input(struct ifnet* ifp, struct mbuf* m)
+{
+ sdla_t *card;
+#if defined(NBPFILTER)
+ struct mbuf m0;
+ u_int32_t af = AF_INET;
+#endif
+
+ if ((card = wanpipe_generic_getcard(ifp)) == NULL){
+ return -EINVAL;
+ }
+ m->m_pkthdr.rcvif = ifp;
+#if defined(NBPFILTER)
+ if (ifp->if_bpf){
+ m0.m_next = m;
+ m0.m_len = 4;
+ m0.m_data = (char*)&af;
+ bpf_mtap(ifp->if_bpf, &m0);
+ }
+#endif
+ ifp->if_ipackets ++;
+ ifp->if_ibytes += m->m_len;
+ sppp_input(ifp, m);
+ return 0;
+}
+
+int wp_lite_set_proto(struct ifnet* ifp, struct ifreq* ifr)
+{
+ wanpipe_common_t* common;
+ struct if_settings* ifsettings;
+ int err = 0;
+
+ if ((common = ifp->if_softc) == NULL){
+ log(LOG_INFO, "%s: Private structure is null!\n",
+ ifp->if_xname);
+ return -EINVAL;
+ }
+ ifsettings = (struct if_settings*)ifr->ifr_data;
+ switch (ifsettings->type) {
+ case IF_PROTO_CISCO:
+ ((struct sppp *)ifp)->pp_flags |= PP_CISCO;
+ ((struct sppp *)ifp)->pp_flags |= PP_KEEPALIVE;
+ break;
+ case IF_PROTO_PPP:
+ ((struct sppp *)ifp)->pp_flags &= ~PP_CISCO;
+ ((struct sppp *)ifp)->pp_flags &= ~PP_KEEPALIVE;
+ break;
+ }
+ err = sppp_ioctl(ifp, SIOCSIFFLAGS, ifr);
+ return err;
+}
+
+/************************************ END **********************************/
diff --git a/sys/dev/pci/if_san_obsd.h b/sys/dev/pci/if_san_obsd.h
new file mode 100644
index 00000000000..26355a75568
--- /dev/null
+++ b/sys/dev/pci/if_san_obsd.h
@@ -0,0 +1,109 @@
+/*-
+ * Copyright (c) 2001-2004 Sangoma Technologies (SAN)
+ * All rights reserved. www.sangoma.com
+ *
+ * This code is written by Alex Feldman <al.feldman@sangoma.com> for SAN.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sangoma Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SANGOMA TECHNOLOGIES AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#ifndef __IF_SAN_OBSD_H
+# define __IF_SAN_OBSD_H
+
+# define IF_IFACE_V35 0x1001
+# define IF_IFACE_T1 0x1002
+# define IF_IFACE_E1 0x1003
+# define IF_IFACE_SYNC_SERIAL 0x1004
+
+# define IF_PROTO_HDLC 0x2001
+# define IF_PROTO_PPP 0x2002
+# define IF_PROTO_CISCO 0x2003
+# define IF_PROTO_FR 0x2004
+# define IF_PROTO_FR_ADD_PVC 0x2005
+# define IF_PROTO_FR_DEL_PVC 0x2006
+# define IF_PROTO_X25 0x2007
+# define WAN_PROTO_X25 0x2007
+
+# define IF_GET_PROTO 0x3001
+
+# define te1_settings void
+# define sync_serial_settings void
+
+# define ifs_size data_length
+# define ifs_te1 data
+# define ifs_sync data
+# define ifs_cisco data
+# define ifs_fr data
+# define ifs_fr_pvc data
+# define ifs_fr_pvc_info data
+
+
+#define WANHDLC_CONF_INTERFACE 0x0001
+#define WANHDLC_CONF_CLOCKING 0x0002
+
+typedef struct {
+ unsigned long mask;
+ char interface;
+ unsigned bps;
+} wan_dev_conf_t;
+
+typedef struct { int dummy; } cisco_proto, fr_proto, fr_proto_pvc;
+struct if_settings
+{
+ unsigned int type;
+ unsigned int data_length;
+ void* data;
+};
+
+typedef struct {
+ int proto;
+ int iface;
+ char hwprobe[100];
+ sdla_te_cfg_t te_cfg;
+ wan_dev_conf_t devconf;
+ union {
+ cisco_proto cisco;
+ fr_proto fr;
+ fr_proto_pvc fr_pvc;
+ } protocol;
+} wanlite_def_t;
+
+/* WANPIPE Generic function interface */
+# if defined(_KERNEL)
+struct ifnet* wanpipe_generic_alloc (sdla_t*);
+void wanpipe_generic_free (struct ifnet*);
+int wanpipe_generic_name (sdla_t*, char*);
+int wanpipe_generic_register(sdla_t*, struct ifnet*, char*);
+void wanpipe_generic_unregister(struct ifnet*);
+int wanpipe_generic_open(struct ifnet*);
+int wanpipe_generic_close(struct ifnet*);
+int wanpipe_generic_input(struct ifnet*, struct mbuf*);
+int wanpipe_generic_tx_timeout(struct ifnet*);
+int wp_lite_set_proto(struct ifnet*, struct ifreq*);
+# endif
+#endif /* __IF_SAN_OBSD_H */
diff --git a/sys/dev/pci/if_san_te1.c b/sys/dev/pci/if_san_te1.c
new file mode 100644
index 00000000000..ed13e225345
--- /dev/null
+++ b/sys/dev/pci/if_san_te1.c
@@ -0,0 +1,3987 @@
+/*-
+ * Copyright (c) 2001-2004 Sangoma Technologies (SAN)
+ * All rights reserved. www.sangoma.com
+ *
+ * This code is written by Alex Feldman <al.feldman@sangoma.com> for SAN.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sangoma Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SANGOMA TECHNOLOGIES AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ ******************************************************************************
+ INCLUDE FILES
+ ******************************************************************************
+*/
+# include </usr/include/bitstring.h>
+# include <sys/types.h>
+# include <sys/param.h>
+# include <sys/systm.h>
+# include <sys/syslog.h>
+# include <sys/ioccom.h>
+# include <sys/malloc.h>
+# include <sys/errno.h>
+# include <sys/mbuf.h>
+# include <sys/socket.h>
+# include <sys/kernel.h>
+# include <sys/time.h>
+# include <sys/timeout.h>
+
+# include <net/if.h>
+# include <net/if_media.h>
+# include <net/if_sppp.h>
+# include <netinet/in_systm.h>
+# include <netinet/in.h>
+# include <netinet/in_var.h>
+# include <netinet/udp.h>
+# include <netinet/ip.h>
+
+# include <dev/pci/if_san_common.h>
+
+/*
+ ******************************************************************************
+ DEFINES AND MACROS
+ ******************************************************************************
+*/
+
+#define FIRST_SAMPLE 0
+#define LAST_SAMPLE 23
+#define FIRST_UI 0
+#define LAST_UI 4
+
+#define MAX_BUSY_READ 0x05
+
+/* Enabling/Disabling register debugging */
+#undef WAN_DEBUG_TE1_REG
+#ifdef WAN_DEBUG_TE1_REG
+
+#define TEST_REG(reg,value) \
+{ \
+ unsigned char test_value = READ_REG(reg); \
+ if (test_value != value){ \
+ log(LOG_INFO, "%s:%d: Test failed!\n", \
+ __FILE__,__LINE__); \
+ log(LOG_INFO, "%s:%d: Reg=%02x, Val=%02x\n", \
+ __FILE__,__LINE__,reg, value); \
+ } \
+}
+
+#define TEST_RPSC_REG(card,reg,channel,value) \
+{ \
+ unsigned char test_value = ReadRPSCReg(card,channel,reg); \
+ if (test_value != value){ \
+ log(LOG_INFO, "%s:%d: RPSC REG Test failed!\n", \
+ __FILE__,__LINE__); \
+ log(LOG_INFO, "%s:%d: Reg=%02x,Channel=%d,Val=%02x!\n", \
+ __FILE__, __LINE__, reg, channel, value); \
+ } \
+}
+
+#define TEST_TPSC_REG(card,reg,channel,value) \
+{ \
+ unsigned char test_value = ReadTPSCReg(card,channel,reg); \
+ if (test_value != value){ \
+ log(LOG_INFO, "%s:%d: TPSC REG Test failed!\n", \
+ __FILE__,__LINE__); \
+ log(LOG_INFO, "%s:%d: Reg=%02x,Channel=%d,Val=%02x)!\n",\
+ __FILE__, __LINE__, reg, channel, value); \
+ } \
+}
+
+#else
+
+#define TEST_REG(reg,value)
+#define TEST_RPSC_REG(card,reg,channel,value)
+#define TEST_TPSC_REG(card,reg,channel,value)
+
+#endif
+
+#define READ_RPSC_REG(reg,channel) ReadRPSCReg(card,reg,channel)
+#define READ_TPSC_REG(reg,channel) ReadTPSCReg(card,reg,channel)
+#define READ_SIGX_REG(reg,channel) ReadSIGXReg(card,reg,channel)
+#define WRITE_RPSC_REG(reg,channel,value) \
+ { \
+ WriteRPSCReg(card,reg,channel,(unsigned char)value); \
+ TEST_RPSC_REG(card,reg,channel,(unsigned char)value); \
+ }
+
+#define WRITE_TPSC_REG(reg,channel,value) \
+ { \
+ WriteTPSCReg(card,reg,channel,(unsigned char)value); \
+ TEST_TPSC_REG(card,reg,channe,(unsigned char)value); \
+ }
+
+#if 0
+#define WRITE_SIGX_REG(reg,channel,value) \
+ { \
+ WriteSIGXReg(card,reg,channel,(unsigned char)value); \
+ TEST_SIGX_REG(card,reg,channel,(unsigned char)value); \
+ }
+#endif
+
+#define IS_T1_ALARM(alarm) ((alarm) & \
+ ( \
+ BIT_RED_ALARM | \
+ BIT_AIS_ALARM | \
+ BIT_YEL_ALARM \
+ ))
+
+#define IS_E1_ALARM(alarm) ((alarm) & \
+ ( \
+ BIT_RED_ALARM | \
+ BIT_AIS_ALARM | \
+ BIT_ALOS_ALARM \
+ ))
+
+/*
+ ******************************************************************************
+ STRUCTURES AND TYPEDEFS
+ ******************************************************************************
+*/
+typedef
+unsigned char TX_WAVEFORM[LAST_SAMPLE-FIRST_SAMPLE+1][LAST_UI-FIRST_UI+1];
+
+typedef struct RLPS_EQUALIZER_RAM_T {
+ /*unsigned char address;*/
+ unsigned char byte1;
+ unsigned char byte2;
+ unsigned char byte3;
+ unsigned char byte4;
+} RLPS_EQUALIZER_RAM;
+
+/*
+ ******************************************************************************
+ GLOBAL VARIABLES
+ ******************************************************************************
+*/
+
+
+/* Transmit Waveform Values for T1 Long Haul (LBO 0db)
+** unsigned char t1_tx_waveform_lh_0db
+** [LAST_SAMPLE-FIRST_SAMPLE+1][LAST_UI-FIRST_UI+1] = */
+TX_WAVEFORM t1_tx_waveform_lh_0db =
+{
+ { 0x00, 0x44, 0x00, 0x00, 0x00 },
+ { 0x0A, 0x44, 0x00, 0x00, 0x00 },
+ { 0x20, 0x43, 0x00, 0x00, 0x00 },
+ { 0x32, 0x43, 0x00, 0x00, 0x00 },
+ { 0x3E, 0x42, 0x00, 0x00, 0x00 },
+ { 0x3D, 0x42, 0x00, 0x00, 0x00 },
+ { 0x3C, 0x41, 0x00, 0x00, 0x00 },
+ { 0x3B, 0x41, 0x00, 0x00, 0x00 },
+ { 0x3A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x39, 0x00, 0x00, 0x00, 0x00 },
+ { 0x39, 0x00, 0x00, 0x00, 0x00 },
+ { 0x38, 0x00, 0x00, 0x00, 0x00 },
+ { 0x37, 0x00, 0x00, 0x00, 0x00 },
+ { 0x36, 0x00, 0x00, 0x00, 0x00 },
+ { 0x34, 0x00, 0x00, 0x00, 0x00 },
+ { 0x29, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4F, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x49, 0x00, 0x00, 0x00, 0x00 },
+ { 0x47, 0x00, 0x00, 0x00, 0x00 },
+ { 0x47, 0x00, 0x00, 0x00, 0x00 },
+ { 0x46, 0x00, 0x00, 0x00, 0x00 },
+ { 0x46, 0x00, 0x00, 0x00, 0x00 }
+};
+
+/* Transmit Waveform Values for T1 Long Haul (LBO 7.5 dB):
+** unsigned char t1_tx_waveform_lh_75db
+** [LAST_SAMPLE-FIRST_SAMPLE+1][LAST_UI-FIRST_UI+1] = */
+TX_WAVEFORM t1_tx_waveform_lh_75db =
+{
+ { 0x00, 0x10, 0x00, 0x00, 0x00 },
+ { 0x01, 0x0E, 0x00, 0x00, 0x00 },
+ { 0x02, 0x0C, 0x00, 0x00, 0x00 },
+ { 0x04, 0x0A, 0x00, 0x00, 0x00 },
+ { 0x08, 0x08, 0x00, 0x00, 0x00 },
+ { 0x0C, 0x06, 0x00, 0x00, 0x00 },
+ { 0x10, 0x04, 0x00, 0x00, 0x00 },
+ { 0x16, 0x02, 0x00, 0x00, 0x00 },
+ { 0x1A, 0x01, 0x00, 0x00, 0x00 },
+ { 0x1E, 0x00, 0x00, 0x00, 0x00 },
+ { 0x22, 0x00, 0x00, 0x00, 0x00 },
+ { 0x26, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2B, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2D, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x28, 0x00, 0x00, 0x00, 0x00 },
+ { 0x24, 0x00, 0x00, 0x00, 0x00 },
+ { 0x20, 0x00, 0x00, 0x00, 0x00 },
+ { 0x1C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x18, 0x00, 0x00, 0x00, 0x00 },
+ { 0x14, 0x00, 0x00, 0x00, 0x00 },
+ { 0x12, 0x00, 0x00, 0x00, 0x00 }
+};
+
+
+/* Transmit Waveform Values for T1 Long Haul (LBO 15 dB)
+** unsigned char t1_tx_waveform_lh_15db
+** [LAST_SAMPLE-FIRST_SAMPLE+1][LAST_UI-FIRST_UI+1] = */
+TX_WAVEFORM t1_tx_waveform_lh_15db =
+{
+ { 0x00, 0x2A, 0x09, 0x01, 0x00 },
+ { 0x00, 0x28, 0x08, 0x01, 0x00 },
+ { 0x00, 0x26, 0x08, 0x01, 0x00 },
+ { 0x00, 0x24, 0x07, 0x01, 0x00 },
+ { 0x01, 0x22, 0x07, 0x01, 0x00 },
+ { 0x02, 0x20, 0x06, 0x01, 0x00 },
+ { 0x04, 0x1E, 0x06, 0x01, 0x00 },
+ { 0x07, 0x1C, 0x05, 0x00, 0x00 },
+ { 0x0A, 0x1B, 0x05, 0x00, 0x00 },
+ { 0x0D, 0x19, 0x05, 0x00, 0x00 },
+ { 0x10, 0x18, 0x04, 0x00, 0x00 },
+ { 0x14, 0x16, 0x04, 0x00, 0x00 },
+ { 0x18, 0x15, 0x04, 0x00, 0x00 },
+ { 0x1B, 0x13, 0x03, 0x00, 0x00 },
+ { 0x1E, 0x12, 0x03, 0x00, 0x00 },
+ { 0x21, 0x10, 0x03, 0x00, 0x00 },
+ { 0x24, 0x0F, 0x03, 0x00, 0x00 },
+ { 0x27, 0x0D, 0x03, 0x00, 0x00 },
+ { 0x2A, 0x0D, 0x02, 0x00, 0x00 },
+ { 0x2D, 0x0B, 0x02, 0x00, 0x00 },
+ { 0x30, 0x0B, 0x02, 0x00, 0x00 },
+ { 0x30, 0x0A, 0x02, 0x00, 0x00 },
+ { 0x2E, 0x0A, 0x02, 0x00, 0x00 },
+ { 0x2C, 0x09, 0x02, 0x00, 0x00 }
+};
+
+
+/* Transmit Waveform Values for T1 Long Haul (LBO 22.5 dB)
+** unsigned char t1_tx_waveform_lh_225db
+** [LAST_SAMPLE-FIRST_SAMPLE+1][LAST_UI-FIRST_UI+1] = */
+TX_WAVEFORM t1_tx_waveform_lh_225db =
+{
+ { 0x00, 0x1F, 0x16, 0x06, 0x01 },
+ { 0x00, 0x20, 0x15, 0x05, 0x01 },
+ { 0x00, 0x21, 0x15, 0x05, 0x01 },
+ { 0x00, 0x22, 0x14, 0x05, 0x01 },
+ { 0x00, 0x22, 0x13, 0x04, 0x00 },
+ { 0x00, 0x23, 0x12, 0x04, 0x00 },
+ { 0x01, 0x23, 0x12, 0x04, 0x00 },
+ { 0x01, 0x24, 0x11, 0x03, 0x00 },
+ { 0x01, 0x23, 0x10, 0x03, 0x00 },
+ { 0x02, 0x23, 0x10, 0x03, 0x00 },
+ { 0x03, 0x22, 0x0F, 0x03, 0x00 },
+ { 0x05, 0x22, 0x0E, 0x03, 0x00 },
+ { 0x07, 0x21, 0x0E, 0x02, 0x00 },
+ { 0x09, 0x20, 0x0D, 0x02, 0x00 },
+ { 0x0B, 0x1E, 0x0C, 0x02, 0x00 },
+ { 0x0E, 0x1D, 0x0C, 0x02, 0x00 },
+ { 0x10, 0x1B, 0x0B, 0x02, 0x00 },
+ { 0x13, 0x1B, 0x0A, 0x02, 0x00 },
+ { 0x15, 0x1A, 0x0A, 0x02, 0x00 },
+ { 0x17, 0x19, 0x09, 0x01, 0x00 },
+ { 0x19, 0x19, 0x08, 0x01, 0x00 },
+ { 0x1B, 0x18, 0x08, 0x01, 0x00 },
+ { 0x1D, 0x17, 0x07, 0x01, 0x00 },
+ { 0x1E, 0x17, 0x06, 0x01, 0x00 }
+};
+
+
+/* Transmit Waveform Values for T1 Short Haul (0 - 110 ft.)
+** unsigned char t1_tx_waveform_sh_110ft
+** [LAST_SAMPLE-FIRST_SAMPLE+1][LAST_UI-FIRST_UI+1] = */
+TX_WAVEFORM t1_tx_waveform_sh_110ft =
+{
+ { 0x00, 0x45, 0x00, 0x00, 0x00 },
+ { 0x0A, 0x44, 0x00, 0x00, 0x00 },
+ { 0x20, 0x43, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x43, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x42, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x42, 0x00, 0x00, 0x00 },
+ { 0x3C, 0x41, 0x00, 0x00, 0x00 },
+ { 0x3B, 0x41, 0x00, 0x00, 0x00 },
+ { 0x3A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x39, 0x00, 0x00, 0x00, 0x00 },
+ { 0x39, 0x00, 0x00, 0x00, 0x00 },
+ { 0x38, 0x00, 0x00, 0x00, 0x00 },
+ { 0x37, 0x00, 0x00, 0x00, 0x00 },
+ { 0x36, 0x00, 0x00, 0x00, 0x00 },
+ { 0x34, 0x00, 0x00, 0x00, 0x00 },
+ { 0x29, 0x00, 0x00, 0x00, 0x00 },
+ { 0x59, 0x00, 0x00, 0x00, 0x00 },
+ { 0x55, 0x00, 0x00, 0x00, 0x00 },
+ { 0x50, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4D, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x48, 0x00, 0x00, 0x00, 0x00 },
+ { 0x46, 0x00, 0x00, 0x00, 0x00 },
+ { 0x46, 0x00, 0x00, 0x00, 0x00 }
+};
+
+
+/* Transmit Waveform Values for T1 Short Haul (110 - 220 ft.)
+** unsigned char t1_tx_waveform_sh_220ft
+** [LAST_SAMPLE-FIRST_SAMPLE+1][LAST_UI-FIRST_UI+1] = */
+TX_WAVEFORM t1_tx_waveform_sh_220ft =
+{
+ { 0x00, 0x44, 0x00, 0x00, 0x00 },
+ { 0x0A, 0x44, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x43, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x43, 0x00, 0x00, 0x00 },
+ { 0x36, 0x42, 0x00, 0x00, 0x00 },
+ { 0x34, 0x42, 0x00, 0x00, 0x00 },
+ { 0x30, 0x41, 0x00, 0x00, 0x00 },
+ { 0x2F, 0x41, 0x00, 0x00, 0x00 },
+ { 0x2E, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2D, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2B, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x28, 0x00, 0x00, 0x00, 0x00 },
+ { 0x26, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x68, 0x00, 0x00, 0x00, 0x00 },
+ { 0x54, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4F, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x49, 0x00, 0x00, 0x00, 0x00 },
+ { 0x47, 0x00, 0x00, 0x00, 0x00 },
+ { 0x47, 0x00, 0x00, 0x00, 0x00 },
+ { 0x46, 0x00, 0x00, 0x00, 0x00 }
+};
+
+
+/* Transmit Waveform Values for T1 Short Haul (220 - 330 ft.)
+** unsigned char t1_tx_waveform_sh_330ft
+** [LAST_SAMPLE-FIRST_SAMPLE+1][LAST_UI-FIRST_UI+1] = */
+TX_WAVEFORM t1_tx_waveform_sh_330ft =
+{
+ { 0x00, 0x44, 0x00, 0x00, 0x00 },
+ { 0x0A, 0x44, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x43, 0x00, 0x00, 0x00 },
+ { 0x3A, 0x43, 0x00, 0x00, 0x00 },
+ { 0x3A, 0x42, 0x00, 0x00, 0x00 },
+ { 0x38, 0x42, 0x00, 0x00, 0x00 },
+ { 0x30, 0x41, 0x00, 0x00, 0x00 },
+ { 0x2F, 0x41, 0x00, 0x00, 0x00 },
+ { 0x2E, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2D, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2B, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x29, 0x00, 0x00, 0x00, 0x00 },
+ { 0x23, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x6C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x60, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4F, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x49, 0x00, 0x00, 0x00, 0x00 },
+ { 0x47, 0x00, 0x00, 0x00, 0x00 },
+ { 0x47, 0x00, 0x00, 0x00, 0x00 },
+ { 0x46, 0x00, 0x00, 0x00, 0x00 }
+};
+
+
+/* Transmit Waveform Values for T1 Short Haul (330 - 440 ft.)
+** unsigned char t1_tx_waveform_sh_440ft
+** [LAST_SAMPLE-FIRST_SAMPLE+1][LAST_UI-FIRST_UI+1] = */
+TX_WAVEFORM t1_tx_waveform_sh_440ft =
+{
+ { 0x00, 0x44, 0x00, 0x00, 0x00 },
+ { 0x0A, 0x44, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x43, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x43, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x42, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x42, 0x00, 0x00, 0x00 },
+ { 0x2F, 0x41, 0x00, 0x00, 0x00 },
+ { 0x2E, 0x41, 0x00, 0x00, 0x00 },
+ { 0x2D, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2C, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2B, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x29, 0x00, 0x00, 0x00, 0x00 },
+ { 0x28, 0x00, 0x00, 0x00, 0x00 },
+ { 0x19, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x7F, 0x00, 0x00, 0x00, 0x00 },
+ { 0x60, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4F, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x49, 0x00, 0x00, 0x00, 0x00 },
+ { 0x47, 0x00, 0x00, 0x00, 0x00 },
+ { 0x47, 0x00, 0x00, 0x00, 0x00 },
+ { 0x46, 0x00, 0x00, 0x00, 0x00 }
+};
+
+
+/* Transmit Waveform Values for T1 Short Haul (440 - 550 ft.)
+** unsigned char t1_tx_waveform_sh_550ft
+** [LAST_SAMPLE-FIRST_SAMPLE+1][LAST_UI-FIRST_UI+1] = */
+TX_WAVEFORM t1_tx_waveform_sh_550ft =
+{
+ { 0x00, 0x44, 0x00, 0x00, 0x00 },
+ { 0x0A, 0x44, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x43, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x43, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x42, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x42, 0x00, 0x00, 0x00 },
+ { 0x30, 0x41, 0x00, 0x00, 0x00 },
+ { 0x2B, 0x41, 0x00, 0x00, 0x00 },
+ { 0x2A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x29, 0x00, 0x00, 0x00, 0x00 },
+ { 0x28, 0x00, 0x00, 0x00, 0x00 },
+ { 0x27, 0x00, 0x00, 0x00, 0x00 },
+ { 0x26, 0x00, 0x00, 0x00, 0x00 },
+ { 0x26, 0x00, 0x00, 0x00, 0x00 },
+ { 0x24, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x7F, 0x00, 0x00, 0x00, 0x00 },
+ { 0x7F, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4F, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x49, 0x00, 0x00, 0x00, 0x00 },
+ { 0x47, 0x00, 0x00, 0x00, 0x00 },
+ { 0x47, 0x00, 0x00, 0x00, 0x00 },
+ { 0x46, 0x00, 0x00, 0x00, 0x00 }
+};
+
+
+/* Transmit Waveform Values for T1 Short Haul (550 - 660 ft.)
+** unsigned char t1_tx_waveform_sh_660ft
+** [LAST_SAMPLE-FIRST_SAMPLE+1][LAST_UI-FIRST_UI+1] = */
+TX_WAVEFORM t1_tx_waveform_sh_660ft =
+{
+ { 0x00, 0x44, 0x00, 0x00, 0x00 },
+ { 0x0A, 0x44, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x43, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x43, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x42, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x42, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x41, 0x00, 0x00, 0x00 },
+ { 0x30, 0x41, 0x00, 0x00, 0x00 },
+ { 0x2A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x29, 0x00, 0x00, 0x00, 0x00 },
+ { 0x28, 0x00, 0x00, 0x00, 0x00 },
+ { 0x27, 0x00, 0x00, 0x00, 0x00 },
+ { 0x26, 0x00, 0x00, 0x00, 0x00 },
+ { 0x25, 0x00, 0x00, 0x00, 0x00 },
+ { 0x24, 0x00, 0x00, 0x00, 0x00 },
+ { 0x4A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x7F, 0x00, 0x00, 0x00, 0x00 },
+ { 0x7F, 0x00, 0x00, 0x00, 0x00 },
+ { 0x5F, 0x00, 0x00, 0x00, 0x00 },
+ { 0x50, 0x00, 0x00, 0x00, 0x00 },
+ { 0x49, 0x00, 0x00, 0x00, 0x00 },
+ { 0x47, 0x00, 0x00, 0x00, 0x00 },
+ { 0x47, 0x00, 0x00, 0x00, 0x00 },
+ { 0x46, 0x00, 0x00, 0x00, 0x00 }
+};
+
+
+/* Transmit Waveform Values for E1 120 Ohm
+** unsigned char e1_tx_waveform_120
+** [LAST_SAMPLE-FIRST_SAMPLE+1][LAST_UI-FIRST_UI+1] = */
+TX_WAVEFORM e1_tx_waveform_120 =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x0A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x00, 0x00, 0x00, 0x00 },
+ { 0x3F, 0x00, 0x00, 0x00, 0x00 },
+ { 0x39, 0x00, 0x00, 0x00, 0x00 },
+ { 0x38, 0x00, 0x00, 0x00, 0x00 },
+ { 0x36, 0x00, 0x00, 0x00, 0x00 },
+ { 0x36, 0x00, 0x00, 0x00, 0x00 },
+ { 0x35, 0x00, 0x00, 0x00, 0x00 },
+ { 0x35, 0x00, 0x00, 0x00, 0x00 },
+ { 0x35, 0x00, 0x00, 0x00, 0x00 },
+ { 0x35, 0x00, 0x00, 0x00, 0x00 },
+ { 0x35, 0x00, 0x00, 0x00, 0x00 },
+ { 0x35, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2D, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+
+/* Transmit Waveform Values for E1 75 Ohm
+** unsigned char e1_tx_waveform_75
+** [LAST_SAMPLE-FIRST_SAMPLE+1][LAST_UI-FIRST_UI+1] = */
+TX_WAVEFORM e1_tx_waveform_75 =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x0A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x28, 0x00, 0x00, 0x00, 0x00 },
+ { 0x3A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x3A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x3A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x3A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x3A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x3A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x3A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x3A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x3A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x3A, 0x00, 0x00, 0x00, 0x00 },
+ { 0x32, 0x00, 0x00, 0x00, 0x00 },
+ { 0x14, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+
+RLPS_EQUALIZER_RAM t1_rlps_ram_table[] =
+{
+ { 0x03, 0xFE, 0x18, 0x40 },
+ { 0x03, 0xF6, 0x18, 0x40 },
+ { 0x03, 0xEE, 0x18, 0x40 },
+ { 0x03, 0xE6, 0x18, 0x40 },
+ { 0x03, 0xDE, 0x18, 0x40 },
+ { 0x03, 0xD6, 0x18, 0x40 },
+ { 0x03, 0xD6, 0x18, 0x40 },
+ { 0x03, 0xD6, 0x18, 0x40 },
+ { 0x03, 0xCE, 0x18, 0x40 },
+ { 0x03, 0xCE, 0x18, 0x40 },
+ { 0x03, 0xCE, 0x18, 0x40 },
+ { 0x03, 0xCE, 0x18, 0x40 },
+ { 0x03, 0xC6, 0x18, 0x40 },
+ { 0x03, 0xC6, 0x18, 0x40 },
+ { 0x03, 0xC6, 0x18, 0x40 },
+ { 0x0B, 0xBE, 0x18, 0x40 },
+ { 0x0B, 0xBE, 0x18, 0x40 },
+ { 0x0B, 0xBE, 0x18, 0x40 },
+ { 0x0B, 0xBE, 0x18, 0x40 },
+ { 0x0B, 0xB6, 0x18, 0x40 },
+ { 0x0B, 0xB6, 0x18, 0x40 },
+ { 0x0B, 0xB6, 0x18, 0x40 },
+ { 0x0B, 0xB6, 0x18, 0x40 },
+ { 0x13, 0xAE, 0x18, 0x38 },
+ { 0x13, 0xAE, 0x18, 0x3C },
+ { 0x13, 0xAE, 0x18, 0x40 },
+ { 0x13, 0xAE, 0x18, 0x40 },
+ { 0x13, 0xAE, 0x18, 0x40 },
+ { 0x13, 0xAE, 0x18, 0x40 },
+ { 0x1B, 0xB6, 0x18, 0xB8 },
+ { 0x1B, 0xAE, 0x18, 0xB8 },
+ { 0x1B, 0xAE, 0x18, 0xBC },
+ { 0x1B, 0xAE, 0x18, 0xC0 },
+ { 0x1B, 0xAE, 0x18, 0xC0 },
+ { 0x23, 0xA6, 0x18, 0xC0 },
+ { 0x23, 0xA6, 0x18, 0xC0 },
+ { 0x23, 0xA6, 0x18, 0xC0 },
+ { 0x23, 0xA6, 0x18, 0xC0 },
+ { 0x23, 0xA6, 0x18, 0xC0 },
+ { 0x23, 0x9E, 0x18, 0xC0 },
+ { 0x23, 0x9E, 0x18, 0xC0 },
+ { 0x23, 0x9E, 0x18, 0xC0 },
+ { 0x23, 0x9E, 0x18, 0xC0 },
+ { 0x23, 0x9E, 0x18, 0xC0 },
+ { 0x2B, 0x96, 0x18, 0xC0 },
+ { 0x2B, 0x96, 0x18, 0xC0 },
+ { 0x2B, 0x96, 0x18, 0xC0 },
+ { 0x33, 0x96, 0x19, 0x40 },
+ { 0x37, 0x96, 0x19, 0x40 },
+ { 0x37, 0x96, 0x19, 0x40 },
+ { 0x37, 0x96, 0x19, 0x40 },
+ { 0x3F, 0x9E, 0x19, 0xC0 },
+ { 0x3F, 0x9E, 0x19, 0xC0 },
+ { 0x3F, 0x9E, 0x19, 0xC0 },
+ { 0x3F, 0xA6, 0x1A, 0x40 },
+ { 0x3F, 0xA6, 0x1A, 0x40 },
+ { 0x3F, 0xA6, 0x1A, 0x40 },
+ { 0x3F, 0xA6, 0x1A, 0x40 },
+ { 0x3F, 0x96, 0x19, 0xC0 },
+ { 0x3F, 0x96, 0x19, 0xC0 },
+ { 0x3F, 0x96, 0x19, 0xC0 },
+ { 0x3F, 0x96, 0x19, 0xC0 },
+ { 0x47, 0x9E, 0x1A, 0x40 },
+ { 0x47, 0x9E, 0x1A, 0x40 },
+ { 0x47, 0x9E, 0x1A, 0x40 },
+ { 0x47, 0x96, 0x1A, 0x40 },
+ { 0x47, 0x96, 0x1A, 0x40 },
+ { 0x47, 0x96, 0x1A, 0x40 },
+ { 0x47, 0x96, 0x1A, 0x40 },
+ { 0x4F, 0x8E, 0x1A, 0x40 },
+ { 0x4F, 0x8E, 0x1A, 0x40 },
+ { 0x4F, 0x8E, 0x1A, 0x40 },
+ { 0x4F, 0x8E, 0x1A, 0x40 },
+ { 0x4F, 0x8E, 0x1A, 0x40 },
+ { 0x57, 0x86, 0x1A, 0x40 },
+ { 0x57, 0x86, 0x1A, 0x40 },
+ { 0x57, 0x86, 0x1A, 0x40 },
+ { 0x57, 0x86, 0x1A, 0x40 },
+ { 0x57, 0x86, 0x1A, 0x40 },
+ { 0x5F, 0x86, 0x1A, 0xC0 },
+ { 0x5F, 0x86, 0x1A, 0xC0 },
+ { 0x5F, 0x86, 0x1A, 0xC0 },
+ { 0x5F, 0x86, 0x1A, 0xC0 },
+ { 0x5F, 0x86, 0x1A, 0xC0 },
+ { 0x5F, 0x86, 0x1A, 0xC0 },
+ { 0x5F, 0x7E, 0x1A, 0xC0 },
+ { 0x5F, 0x7E, 0x1A, 0xC0 },
+ { 0x5F, 0x7E, 0x1A, 0xC0 },
+ { 0x5F, 0x7E, 0x1A, 0xC0 },
+ { 0x5F, 0x7E, 0x1A, 0xC0 },
+ { 0x67, 0x7E, 0x2A, 0xC0 },
+ { 0x67, 0x7E, 0x2A, 0xC0 },
+ { 0x67, 0x7E, 0x2A, 0xC0 },
+ { 0x67, 0x7E, 0x2A, 0xC0 },
+ { 0x67, 0x76, 0x2A, 0xC0 },
+ { 0x67, 0x76, 0x2A, 0xC0 },
+ { 0x67, 0x76, 0x2A, 0xC0 },
+ { 0x67, 0x76, 0x2A, 0xC0 },
+ { 0x67, 0x76, 0x2A, 0xC0 },
+ { 0x6F, 0x6E, 0x2A, 0xC0 },
+ { 0x6F, 0x6E, 0x2A, 0xC0 },
+ { 0x6F, 0x6E, 0x2A, 0xC0 },
+ { 0x6F, 0x6E, 0x2A, 0xC0 },
+ { 0x77, 0x6E, 0x3A, 0xC0 },
+ { 0x77, 0x6E, 0x3A, 0xC0 },
+ { 0x77, 0x6E, 0x3A, 0xC0 },
+ { 0x77, 0x6E, 0x3A, 0xC0 },
+ { 0x7F, 0x66, 0x3A, 0xC0 },
+ { 0x7F, 0x66, 0x3A, 0xC0 },
+ { 0x7F, 0x66, 0x4A, 0xC0 },
+ { 0x7F, 0x66, 0x4A, 0xC0 },
+ { 0x7F, 0x66, 0x4A, 0xC0 },
+ { 0x7F, 0x66, 0x4A, 0xC0 },
+ { 0x87, 0x66, 0x5A, 0xC0 },
+ { 0x87, 0x66, 0x5A, 0xC0 },
+ { 0x87, 0x66, 0x5A, 0xC0 },
+ { 0x87, 0x66, 0x5A, 0xC0 },
+ { 0x87, 0x66, 0x5A, 0xC0 },
+ { 0x87, 0x5E, 0x5A, 0xC0 },
+ { 0x87, 0x5E, 0x5A, 0xC0 },
+ { 0x87, 0x5E, 0x5A, 0xC0 },
+ { 0x87, 0x5E, 0x5A, 0xC0 },
+ { 0x87, 0x5E, 0x5A, 0xC0 },
+ { 0x8F, 0x5E, 0x6A, 0xC0 },
+ { 0x8F, 0x5E, 0x6A, 0xC0 },
+ { 0x8F, 0x5E, 0x6A, 0xC0 },
+ { 0x8F, 0x5E, 0x6A, 0xC0 },
+ { 0x97, 0x5E, 0x7A, 0xC0 },
+ { 0x97, 0x5E, 0x7A, 0xC0 },
+ { 0x97, 0x5E, 0x7A, 0xC0 },
+ { 0x97, 0x5E, 0x7A, 0xC0 },
+ { 0x9F, 0x5E, 0x8A, 0xC0 },
+ { 0x9F, 0x5E, 0x8A, 0xC0 },
+ { 0x9F, 0x5E, 0x8A, 0xC0 },
+ { 0x9F, 0x5E, 0x8A, 0xC0 },
+ { 0x9F, 0x5E, 0x8A, 0xC0 },
+ { 0xA7, 0x56, 0x9A, 0xC0 },
+ { 0xA7, 0x56, 0x9A, 0xC0 },
+ { 0xA7, 0x56, 0x9A, 0xC0 },
+ { 0xA7, 0x56, 0x9A, 0xC0 },
+ { 0xA7, 0x56, 0xAA, 0xC0 },
+ { 0xA7, 0x56, 0xAA, 0xC0 },
+ { 0xA7, 0x56, 0xAA, 0xC0 },
+ { 0xAF, 0x4E, 0xAA, 0xC0 },
+ { 0xAF, 0x4E, 0xAA, 0xC0 },
+ { 0xAF, 0x4E, 0xAA, 0xC0 },
+ { 0xAF, 0x4E, 0xAA, 0xC0 },
+ { 0xAF, 0x4E, 0xAA, 0xC0 },
+ { 0xB7, 0x46, 0xAA, 0xC0 },
+ { 0xB7, 0x46, 0xAA, 0xC0 },
+ { 0xB7, 0x46, 0xAA, 0xC0 },
+ { 0xB7, 0x46, 0xAA, 0xC0 },
+ { 0xB7, 0x46, 0xAA, 0xC0 },
+ { 0xB7, 0x46, 0xAA, 0xC0 },
+ { 0xB7, 0x46, 0xAA, 0xC0 },
+ { 0xB7, 0x46, 0xBA, 0xC0 },
+ { 0xB7, 0x46, 0xBA, 0xC0 },
+ { 0xB7, 0x46, 0xBA, 0xC0 },
+ { 0xBF, 0x4E, 0xBB, 0x40 },
+ { 0xBF, 0x4E, 0xBB, 0x40 },
+ { 0xBF, 0x4E, 0xBB, 0x40 },
+ { 0xBF, 0x4E, 0xBB, 0x40 },
+ { 0xBF, 0x4E, 0xBB, 0x40 },
+ { 0xBF, 0x4E, 0xBB, 0x40 },
+ { 0xBF, 0x4E, 0xBB, 0x40 },
+ { 0xBF, 0x4E, 0xBB, 0x40 },
+ { 0xBF, 0x4E, 0xBB, 0x40 },
+ { 0xBE, 0x46, 0xCB, 0x40 },
+ { 0xBE, 0x46, 0xCB, 0x40 },
+ { 0xBE, 0x46, 0xCB, 0x40 },
+ { 0xBE, 0x46, 0xCB, 0x40 },
+ { 0xBE, 0x46, 0xCB, 0x40 },
+ { 0xBE, 0x46, 0xCB, 0x40 },
+ { 0xBE, 0x46, 0xDB, 0x40 },
+ { 0xBE, 0x46, 0xDB, 0x40 },
+ { 0xBE, 0x46, 0xDB, 0x40 },
+ { 0xC6, 0x3E, 0xCB, 0x40 },
+ { 0xC6, 0x3E, 0xCB, 0x40 },
+ { 0xC6, 0x3E, 0xDB, 0x40 },
+ { 0xC6, 0x3E, 0xDB, 0x40 },
+ { 0xC6, 0x3E, 0xDB, 0x40 },
+ { 0xC6, 0x44, 0xDB, 0x40 },
+ { 0xC6, 0x44, 0xDB, 0x40 },
+ { 0xC6, 0x44, 0xDB, 0x40 },
+ { 0xC6, 0x44, 0xDB, 0x40 },
+ { 0xC6, 0x3C, 0xDB, 0x40 },
+ { 0xC6, 0x3C, 0xDB, 0x40 },
+ { 0xC6, 0x3C, 0xDB, 0x40 },
+ { 0xC6, 0x3C, 0xDB, 0x40 },
+ { 0xD6, 0x34, 0xDB, 0x40 },
+ { 0xD6, 0x34, 0xDB, 0x40 },
+ { 0xD6, 0x34, 0xDB, 0x40 },
+ { 0xD6, 0x34, 0xDB, 0x40 },
+ { 0xD6, 0x34, 0xDB, 0x40 },
+ { 0xDE, 0x2C, 0xDB, 0x3C },
+ { 0xDE, 0x2C, 0xDB, 0x3C },
+ { 0xDE, 0x2C, 0xDB, 0x3C },
+ { 0xE6, 0x2C, 0xDB, 0x40 },
+ { 0xE6, 0x2C, 0xDB, 0x40 },
+ { 0xE6, 0x2C, 0xDB, 0x40 },
+ { 0xE6, 0x2C, 0xDB, 0x40 },
+ { 0xE6, 0x2C, 0xDB, 0x40 },
+ { 0xE6, 0x2C, 0xEB, 0x40 },
+ { 0xE6, 0x2C, 0xEB, 0x40 },
+ { 0xE6, 0x2C, 0xEB, 0x40 },
+ { 0xEE, 0x2C, 0xFB, 0x40 },
+ { 0xEE, 0x2C, 0xFB, 0x40 },
+ { 0xEE, 0x2C, 0xFB, 0x40 },
+ { 0xEE, 0x2D, 0x0B, 0x40 },
+ { 0xEE, 0x2D, 0x0B, 0x40 },
+ { 0xEE, 0x2D, 0x0B, 0x40 },
+ { 0xEE, 0x2D, 0x0B, 0x40 },
+ { 0xEE, 0x2D, 0x0B, 0x40 },
+ { 0xF5, 0x25, 0x0B, 0x38 },
+ { 0xF5, 0x25, 0x0B, 0x3C },
+ { 0xF5, 0x25, 0x0B, 0x40 },
+ { 0xF5, 0x25, 0x1B, 0x40 },
+ { 0xF5, 0x25, 0x1B, 0x40 },
+ { 0xF5, 0x25, 0x1B, 0x40 },
+ { 0xF5, 0x25, 0x1B, 0x40 },
+ { 0xF5, 0x25, 0x1B, 0x40 },
+ { 0xFD, 0x25, 0x2B, 0x40 },
+ { 0xFD, 0x25, 0x2B, 0x40 },
+ { 0xFD, 0x25, 0x2B, 0x40 },
+ { 0xFD, 0x25, 0x2B, 0x40 },
+ { 0xFD, 0x25, 0x27, 0x40 },
+ { 0xFD, 0x25, 0x27, 0x40 },
+ { 0xFD, 0x25, 0x27, 0x40 },
+ { 0xFD, 0x25, 0x23, 0x40 },
+ { 0xFD, 0x25, 0x23, 0x40 },
+ { 0xFD, 0x25, 0x23, 0x40 },
+ { 0xFD, 0x25, 0x33, 0x40 },
+ { 0xFD, 0x25, 0x33, 0x40 },
+ { 0xFD, 0x25, 0x33, 0x40 },
+ { 0xFD, 0x25, 0x33, 0x40 },
+ { 0xFD, 0x25, 0x33, 0x40 },
+ { 0xFD, 0x25, 0x33, 0x40 },
+ { 0xFC, 0x25, 0x33, 0x40 },
+ { 0xFC, 0x25, 0x33, 0x40 },
+ { 0xFC, 0x25, 0x43, 0x40 },
+ { 0xFC, 0x25, 0x43, 0x40 },
+ { 0xFC, 0x25, 0x43, 0x40 },
+ { 0xFC, 0x25, 0x43, 0x44 },
+ { 0xFC, 0x25, 0x43, 0x48 },
+ { 0xFC, 0x25, 0x43, 0x4C },
+ { 0xFC, 0x25, 0x43, 0xBC },
+ { 0xFC, 0x25, 0x43, 0xC0 },
+ { 0xFC, 0x25, 0x43, 0xC0 },
+ { 0xFC, 0x23, 0x43, 0xC0 },
+ { 0xFC, 0x23, 0x43, 0xC0 },
+ { 0xFC, 0x23, 0x43, 0xC0 },
+ { 0xFC, 0x21, 0x43, 0xC0 },
+ { 0xFC, 0x21, 0x43, 0xC0 },
+ { 0xFC, 0x21, 0x53, 0xC0 },
+ { 0xFC, 0x21, 0x53, 0xC0 },
+ { 0xFC, 0x21, 0x53, 0xC0 }
+};
+
+RLPS_EQUALIZER_RAM t1_rlps_perf_mode_ram_table[] =
+{
+ { 0x03, 0xFE, 0x18, 0x40 },
+ { 0x03, 0xFE, 0x18, 0x40 },
+ { 0x03, 0xFE, 0x18, 0x40 },
+ { 0x03, 0xFE, 0x18, 0x40 },
+ { 0x03, 0xFE, 0x18, 0x40 },
+ { 0x03, 0xFE, 0x18, 0x40 },
+ { 0x03, 0xFE, 0x18, 0x40 },
+ { 0x03, 0xFE, 0x18, 0x40 },
+ { 0x03, 0xF6, 0x18, 0x40 },
+ { 0x03, 0xF6, 0x18, 0x40 },
+ { 0x03, 0xF6, 0x18, 0x40 },
+ { 0x03, 0xF6, 0x18, 0x40 },
+ { 0x03, 0xF6, 0x18, 0x40 },
+ { 0x03, 0xF6, 0x18, 0x40 },
+ { 0x03, 0xF6, 0x18, 0x40 },
+ { 0x03, 0xF6, 0x18, 0x40 },
+ { 0x03, 0xEE, 0x18, 0x40 },
+ { 0x03, 0xEE, 0x18, 0x40 },
+ { 0x03, 0xEE, 0x18, 0x40 },
+ { 0x03, 0xEE, 0x18, 0x40 },
+ { 0x03, 0xEE, 0x18, 0x40 },
+ { 0x03, 0xEE, 0x18, 0x40 },
+ { 0x03, 0xEE, 0x18, 0x40 },
+ { 0x03, 0xEE, 0x18, 0x40 },
+ { 0x03, 0xE6, 0x18, 0x40 },
+ { 0x03, 0xE6, 0x18, 0x40 },
+ { 0x03, 0xE6, 0x18, 0x40 },
+ { 0x03, 0xE6, 0x18, 0x40 },
+ { 0x03, 0xE6, 0x18, 0x40 },
+ { 0x03, 0xE6, 0x18, 0x40 },
+ { 0x03, 0xE6, 0x18, 0x40 },
+ { 0x03, 0xE6, 0x18, 0x40 },
+ { 0x03, 0xDE, 0x18, 0x40 },
+ { 0x03, 0xDE, 0x18, 0x40 },
+ { 0x03, 0xDE, 0x18, 0x40 },
+ { 0x03, 0xDE, 0x18, 0x40 },
+ { 0x03, 0xDE, 0x18, 0x40 },
+ { 0x03, 0xDE, 0x18, 0x40 },
+ { 0x03, 0xDE, 0x18, 0x40 },
+ { 0x03, 0xDE, 0x18, 0x40 },
+ { 0x03, 0xD6, 0x18, 0x40 },
+ { 0x03, 0xD6, 0x18, 0x40 },
+ { 0x03, 0xD6, 0x18, 0x40 },
+ { 0x03, 0xD6, 0x18, 0x40 },
+ { 0x03, 0xD6, 0x18, 0x40 },
+ { 0x03, 0xD6, 0x18, 0x40 },
+ { 0x03, 0xD6, 0x18, 0x40 },
+ { 0x03, 0xD6, 0x18, 0x40 },
+ { 0x03, 0xCE, 0x18, 0x40 },
+ { 0x03, 0xCE, 0x18, 0x40 },
+ { 0x03, 0xCE, 0x18, 0x40 },
+ { 0x03, 0xCE, 0x18, 0x40 },
+ { 0x03, 0xCE, 0x18, 0x40 },
+ { 0x03, 0xCE, 0x18, 0x40 },
+ { 0x03, 0xCE, 0x18, 0x40 },
+ { 0x03, 0xCE, 0x18, 0x40 },
+ { 0x03, 0xC6, 0x18, 0x40 },
+ { 0x03, 0xC6, 0x18, 0x40 },
+ { 0x03, 0xC6, 0x18, 0x40 },
+ { 0x03, 0xC6, 0x18, 0x40 },
+ { 0x03, 0xC6, 0x18, 0x40 },
+ { 0x03, 0xC6, 0x18, 0x40 },
+ { 0x03, 0xC6, 0x18, 0x40 },
+ { 0x03, 0xC6, 0x18, 0x40 },
+ { 0x03, 0xBE, 0x18, 0x40 },
+ { 0x03, 0xBE, 0x18, 0x40 },
+ { 0x03, 0xBE, 0x18, 0x40 },
+ { 0x03, 0xBE, 0x18, 0x40 },
+ { 0x03, 0xBE, 0x18, 0x40 },
+ { 0x03, 0xBE, 0x18, 0x40 },
+ { 0x03, 0xBE, 0x18, 0x40 },
+ { 0x03, 0xBE, 0x18, 0x40 },
+ { 0x03, 0xB6, 0x18, 0x40 },
+ { 0x03, 0xB6, 0x18, 0x40 },
+ { 0x03, 0xB6, 0x18, 0x40 },
+ { 0x03, 0xB6, 0x18, 0x40 },
+ { 0x03, 0xB6, 0x18, 0x40 },
+ { 0x03, 0xB6, 0x18, 0x40 },
+ { 0x03, 0xB6, 0x18, 0x40 },
+ { 0x03, 0xB6, 0x18, 0x40 },
+ { 0x03, 0xA6, 0x18, 0x40 },
+ { 0x03, 0xA6, 0x18, 0x40 },
+ { 0x03, 0xA6, 0x18, 0x40 },
+ { 0x03, 0xA6, 0x18, 0x40 },
+ { 0x03, 0xA6, 0x18, 0x40 },
+ { 0x03, 0xA6, 0x18, 0x40 },
+ { 0x03, 0xA6, 0x18, 0x40 },
+ { 0x03, 0xA6, 0x18, 0x40 },
+ { 0x03, 0x9E, 0x18, 0x40 },
+ { 0x03, 0x9E, 0x18, 0x40 },
+ { 0x03, 0x9E, 0x18, 0x40 },
+ { 0x03, 0x9E, 0x18, 0x40 },
+ { 0x03, 0x9E, 0x18, 0x40 },
+ { 0x03, 0x9E, 0x18, 0x40 },
+ { 0x03, 0x9E, 0x18, 0x40 },
+ { 0x03, 0x9E, 0x18, 0x40 },
+ { 0x03, 0x96, 0x18, 0x40 },
+ { 0x03, 0x96, 0x18, 0x40 },
+ { 0x03, 0x96, 0x18, 0x40 },
+ { 0x03, 0x96, 0x18, 0x40 },
+ { 0x03, 0x96, 0x18, 0x40 },
+ { 0x03, 0x96, 0x18, 0x40 },
+ { 0x03, 0x96, 0x18, 0x40 },
+ { 0x03, 0x96, 0x18, 0x40 },
+ { 0x03, 0x8E, 0x18, 0x40 },
+ { 0x03, 0x8E, 0x18, 0x40 },
+ { 0x03, 0x8E, 0x18, 0x40 },
+ { 0x03, 0x8E, 0x18, 0x40 },
+ { 0x03, 0x8E, 0x18, 0x40 },
+ { 0x03, 0x8E, 0x18, 0x40 },
+ { 0x03, 0x8E, 0x18, 0x40 },
+ { 0x03, 0x8E, 0x18, 0x40 },
+ { 0x03, 0x86, 0x18, 0x40 },
+ { 0x03, 0x86, 0x18, 0x40 },
+ { 0x03, 0x86, 0x18, 0x40 },
+ { 0x03, 0x86, 0x18, 0x40 },
+ { 0x03, 0x86, 0x18, 0x40 },
+ { 0x03, 0x86, 0x18, 0x40 },
+ { 0x03, 0x86, 0x18, 0x40 },
+ { 0x03, 0x86, 0x18, 0x40 },
+ { 0x03, 0x7E, 0x18, 0x40 },
+ { 0x03, 0x7E, 0x18, 0x40 },
+ { 0x03, 0x7E, 0x18, 0x40 },
+ { 0x03, 0x7E, 0x18, 0x40 },
+ { 0x03, 0x7E, 0x18, 0x40 },
+ { 0x03, 0x7E, 0x18, 0x40 },
+ { 0x03, 0x7E, 0x18, 0x40 },
+ { 0x03, 0x7E, 0x18, 0x40 },
+ { 0x03, 0x76, 0x18, 0x40 },
+ { 0x03, 0x76, 0x18, 0x40 },
+ { 0x03, 0x76, 0x18, 0x40 },
+ { 0x03, 0x76, 0x18, 0x40 },
+ { 0x03, 0x76, 0x18, 0x40 },
+ { 0x03, 0x76, 0x18, 0x40 },
+ { 0x03, 0x76, 0x18, 0x40 },
+ { 0x03, 0x76, 0x18, 0x40 },
+ { 0x03, 0x6E, 0x18, 0x40 },
+ { 0x03, 0x6E, 0x18, 0x40 },
+ { 0x03, 0x6E, 0x18, 0x40 },
+ { 0x03, 0x6E, 0x18, 0x40 },
+ { 0x03, 0x6E, 0x18, 0x40 },
+ { 0x03, 0x6E, 0x18, 0x40 },
+ { 0x03, 0x6E, 0x18, 0x40 },
+ { 0x03, 0x6E, 0x18, 0x40 },
+ { 0x03, 0x66, 0x18, 0x40 },
+ { 0x03, 0x66, 0x18, 0x40 },
+ { 0x03, 0x66, 0x18, 0x40 },
+ { 0x03, 0x66, 0x18, 0x40 },
+ { 0x03, 0x66, 0x18, 0x40 },
+ { 0x03, 0x66, 0x18, 0x40 },
+ { 0x03, 0x66, 0x18, 0x40 },
+ { 0x03, 0x66, 0x18, 0x40 },
+ { 0x03, 0x5E, 0x18, 0x40 },
+ { 0x03, 0x5E, 0x18, 0x40 },
+ { 0x03, 0x5E, 0x18, 0x40 },
+ { 0x03, 0x5E, 0x18, 0x40 },
+ { 0x03, 0x5E, 0x18, 0x40 },
+ { 0x03, 0x5E, 0x18, 0x40 },
+ { 0x03, 0x5E, 0x18, 0x40 },
+ { 0x03, 0x5E, 0x18, 0x40 },
+ { 0x03, 0x56, 0x18, 0x40 },
+ { 0x03, 0x56, 0x18, 0x40 },
+ { 0x03, 0x56, 0x18, 0x40 },
+ { 0x03, 0x56, 0x18, 0x40 },
+ { 0x03, 0x56, 0x18, 0x40 },
+ { 0x03, 0x56, 0x18, 0x40 },
+ { 0x03, 0x56, 0x18, 0x40 },
+ { 0x03, 0x56, 0x18, 0x40 },
+ { 0x03, 0x4E, 0x18, 0x40 },
+ { 0x03, 0x4E, 0x18, 0x40 },
+ { 0x03, 0x4E, 0x18, 0x40 },
+ { 0x03, 0x4E, 0x18, 0x40 },
+ { 0x03, 0x4E, 0x18, 0x40 },
+ { 0x03, 0x4E, 0x18, 0x40 },
+ { 0x03, 0x4E, 0x18, 0x40 },
+ { 0x03, 0x4E, 0x18, 0x40 },
+ { 0x03, 0x46, 0x18, 0x40 },
+ { 0x03, 0x46, 0x18, 0x40 },
+ { 0x03, 0x46, 0x18, 0x40 },
+ { 0x03, 0x46, 0x18, 0x40 },
+ { 0x03, 0x46, 0x18, 0x40 },
+ { 0x03, 0x46, 0x18, 0x40 },
+ { 0x03, 0x46, 0x18, 0x40 },
+ { 0x03, 0x46, 0x18, 0x40 },
+ { 0x03, 0x3E, 0x18, 0x40 },
+ { 0x03, 0x3E, 0x18, 0x40 },
+ { 0x03, 0x3E, 0x18, 0x40 },
+ { 0x03, 0x3E, 0x18, 0x40 },
+ { 0x03, 0x3E, 0x18, 0x40 },
+ { 0x03, 0x3E, 0x18, 0x40 },
+ { 0x03, 0x3E, 0x18, 0x40 },
+ { 0x03, 0x3E, 0x18, 0x40 },
+ { 0x03, 0x36, 0x18, 0x40 },
+ { 0x03, 0x36, 0x18, 0x40 },
+ { 0x03, 0x36, 0x18, 0x40 },
+ { 0x03, 0x36, 0x18, 0x40 },
+ { 0x03, 0x36, 0x18, 0x40 },
+ { 0x03, 0x36, 0x18, 0x40 },
+ { 0x03, 0x36, 0x18, 0x40 },
+ { 0x03, 0x36, 0x18, 0x40 },
+ { 0x03, 0x2E, 0x18, 0x40 },
+ { 0x03, 0x2E, 0x18, 0x40 },
+ { 0x03, 0x2E, 0x18, 0x40 },
+ { 0x03, 0x2E, 0x18, 0x40 },
+ { 0x03, 0x2E, 0x18, 0x40 },
+ { 0x03, 0x2E, 0x18, 0x40 },
+ { 0x03, 0x2E, 0x18, 0x40 },
+ { 0x03, 0x2E, 0x18, 0x40 },
+ { 0x03, 0x26, 0x18, 0x40 },
+ { 0x03, 0x26, 0x18, 0x40 },
+ { 0x03, 0x26, 0x18, 0x40 },
+ { 0x03, 0x26, 0x18, 0x40 },
+ { 0x03, 0x26, 0x18, 0x40 },
+ { 0x03, 0x26, 0x18, 0x40 },
+ { 0x03, 0x26, 0x18, 0x40 },
+ { 0x03, 0x26, 0x18, 0x40 },
+ { 0x03, 0x1E, 0x18, 0x40 },
+ { 0x03, 0x1E, 0x18, 0x40 },
+ { 0x03, 0x1E, 0x18, 0x40 },
+ { 0x03, 0x1E, 0x18, 0x40 },
+ { 0x03, 0x1E, 0x18, 0x40 },
+ { 0x03, 0x1E, 0x18, 0x40 },
+ { 0x03, 0x1E, 0x18, 0x40 },
+ { 0x03, 0x1E, 0x18, 0x40 },
+ { 0x03, 0x16, 0x18, 0x40 },
+ { 0x03, 0x16, 0x18, 0x40 },
+ { 0x03, 0x16, 0x18, 0x40 },
+ { 0x03, 0x16, 0x18, 0x40 },
+ { 0x03, 0x16, 0x18, 0x40 },
+ { 0x03, 0x16, 0x18, 0x40 },
+ { 0x03, 0x16, 0x18, 0x40 },
+ { 0x03, 0x16, 0x18, 0x40 },
+ { 0x03, 0x0E, 0x18, 0x40 },
+ { 0x03, 0x0E, 0x18, 0x40 },
+ { 0x03, 0x0E, 0x18, 0x40 },
+ { 0x03, 0x0E, 0x18, 0x40 },
+ { 0x03, 0x0E, 0x18, 0x40 },
+ { 0x03, 0x0E, 0x18, 0x40 },
+ { 0x03, 0x0E, 0x18, 0x40 },
+ { 0x03, 0x0E, 0x18, 0x40 },
+ { 0x03, 0x0E, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 },
+ { 0x03, 0x06, 0x18, 0x40 }
+};
+
+RLPS_EQUALIZER_RAM e1_rlps_ram_table[] =
+{
+ { 0x07, 0xDE, 0x18, 0x2C },
+ { 0x07, 0xDE, 0x18, 0x2C },
+ { 0x07, 0xD6, 0x18, 0x2C },
+ { 0x07, 0xD6, 0x18, 0x2C },
+ { 0x07, 0xD6, 0x18, 0x2C },
+ { 0x07, 0xCE, 0x18, 0x2C },
+ { 0x07, 0xCE, 0x18, 0x2C },
+ { 0x07, 0xCE, 0x18, 0x2C },
+ { 0x07, 0xC6, 0x18, 0x2C },
+ { 0x07, 0xC6, 0x18, 0x2C },
+ { 0x07, 0xC6, 0x18, 0x2C },
+ { 0x07, 0xBE, 0x18, 0x2C },
+ { 0x07, 0xBE, 0x18, 0x2C },
+ { 0x07, 0xBE, 0x18, 0x2C },
+ { 0x07, 0xBE, 0x18, 0x2C },
+ { 0x07, 0xBE, 0x18, 0x2C },
+ { 0x07, 0xB6, 0x18, 0x2C },
+ { 0x07, 0xB6, 0x18, 0x2C },
+ { 0x07, 0xB6, 0x18, 0x2C },
+ { 0x07, 0xB6, 0x18, 0x2C },
+ { 0x07, 0xB6, 0x18, 0x2C },
+ { 0x07, 0xAE, 0x18, 0x2C },
+ { 0x07, 0xAE, 0x18, 0x2C },
+ { 0x07, 0xAE, 0x18, 0x2C },
+ { 0x07, 0xAE, 0x18, 0x2C },
+ { 0x07, 0xAE, 0x18, 0x2C },
+ { 0x07, 0xB6, 0x18, 0xAC },
+ { 0x07, 0xAE, 0x18, 0xAC },
+ { 0x07, 0xAE, 0x18, 0xAC },
+ { 0x07, 0xAE, 0x18, 0xAC },
+ { 0x07, 0xAE, 0x18, 0xAC },
+ { 0x07, 0xA6, 0x18, 0xAC },
+ { 0x07, 0xA6, 0x18, 0xAC },
+ { 0x07, 0xA6, 0x18, 0xAC },
+ { 0x07, 0xA6, 0x18, 0xAC },
+ { 0x07, 0x9E, 0x18, 0xAC },
+ { 0x07, 0xA6, 0x19, 0x2C },
+ { 0x07, 0xA6, 0x19, 0x2C },
+ { 0x07, 0xA6, 0x19, 0x2C },
+ { 0x0F, 0xA6, 0x19, 0x2C },
+ { 0x0F, 0xA6, 0x19, 0x2C },
+ { 0x0F, 0x9E, 0x19, 0x2C },
+ { 0x0F, 0x9E, 0x19, 0x2C },
+ { 0x0F, 0x9E, 0x19, 0x2C },
+ { 0x17, 0x9E, 0x19, 0x2C },
+ { 0x17, 0xA6, 0x19, 0xAC },
+ { 0x17, 0x9E, 0x19, 0xAC },
+ { 0x17, 0x9E, 0x19, 0xAC },
+ { 0x17, 0x96, 0x19, 0xAC },
+ { 0x1F, 0x96, 0x19, 0xAC },
+ { 0x1F, 0x96, 0x19, 0xAC },
+ { 0x1F, 0x8E, 0x19, 0xAC },
+ { 0x1F, 0x8E, 0x19, 0xAC },
+ { 0x1F, 0x8E, 0x19, 0xAC },
+ { 0x27, 0x8E, 0x19, 0xAC },
+ { 0x27, 0x8E, 0x1A, 0x2C },
+ { 0x27, 0x8E, 0x1A, 0x2C },
+ { 0x27, 0x8E, 0x1A, 0x2C },
+ { 0x27, 0x8E, 0x1A, 0x2C },
+ { 0x2F, 0x86, 0x1A, 0x2C },
+ { 0x2F, 0x86, 0x1A, 0x2C },
+ { 0x2F, 0x86, 0x1A, 0x2C },
+ { 0x2F, 0x7E, 0x1A, 0x2C },
+ { 0x2F, 0x7E, 0x1A, 0x2C },
+ { 0x2F, 0x7E, 0x1A, 0x2C },
+ { 0x37, 0x7E, 0x1A, 0x2C },
+ { 0x37, 0x7E, 0x1A, 0xAC },
+ { 0x37, 0x7E, 0x1A, 0xAC },
+ { 0x37, 0x7E, 0x1A, 0xAC },
+ { 0x37, 0x7E, 0x1A, 0xAC },
+ { 0x3F, 0x7E, 0x2A, 0xAC },
+ { 0x3F, 0x7E, 0x2A, 0xAC },
+ { 0x3F, 0x76, 0x2A, 0xAC },
+ { 0x3F, 0x86, 0x2B, 0x2C },
+ { 0x3F, 0x7E, 0x2B, 0x2C },
+ { 0x47, 0x7E, 0x2B, 0x2C },
+ { 0x47, 0x7E, 0x2F, 0x2C },
+ { 0x47, 0x7E, 0x2F, 0x2C },
+ { 0x47, 0x7E, 0x2F, 0x2C },
+ { 0x47, 0x76, 0x2F, 0x2C },
+ { 0x4F, 0x76, 0x2F, 0x2C },
+ { 0x4F, 0x76, 0x2F, 0x2C },
+ { 0x4F, 0x6E, 0x2F, 0x2C },
+ { 0x4F, 0x6E, 0x2F, 0x2C },
+ { 0x4F, 0x6E, 0x2F, 0x2C },
+ { 0x57, 0x6E, 0x2F, 0x2C },
+ { 0x57, 0x6E, 0x2F, 0x2C },
+ { 0x57, 0x6E, 0x3F, 0x2C },
+ { 0x57, 0x6E, 0x3F, 0x2C },
+ { 0x57, 0x6E, 0x3F, 0x2C },
+ { 0x5F, 0x6E, 0x3F, 0x2C },
+ { 0x5F, 0x6E, 0x4F, 0x2C },
+ { 0x5F, 0x6E, 0x4F, 0x2C },
+ { 0x5F, 0x6E, 0x4F, 0x2C },
+ { 0x5F, 0x66, 0x4F, 0x2C },
+ { 0x67, 0x66, 0x4F, 0x2C },
+ { 0x67, 0x66, 0x4F, 0x2C },
+ { 0x67, 0x5E, 0x4F, 0x2C },
+ { 0x67, 0x5E, 0x4F, 0x2C },
+ { 0x67, 0x66, 0x4F, 0x2C },
+ { 0x67, 0x66, 0x4F, 0x2C },
+ { 0x67, 0x66, 0x5F, 0x2C },
+ { 0x6F, 0x6E, 0x5F, 0x2C },
+ { 0x6F, 0x6E, 0x6F, 0x2C },
+ { 0x6F, 0x6E, 0x6F, 0x2C },
+ { 0x6F, 0x6E, 0x7F, 0x2C },
+ { 0x6F, 0x6E, 0x7F, 0x2C },
+ { 0x6F, 0x6E, 0x7F, 0x2C },
+ { 0x77, 0x66, 0x7F, 0x2C },
+ { 0x77, 0x66, 0x7F, 0x2C },
+ { 0x77, 0x5E, 0x6F, 0x2C },
+ { 0x77, 0x5E, 0x7F, 0x2C },
+ { 0x77, 0x5E, 0x7F, 0x2C },
+ { 0x7F, 0x5E, 0x7F, 0x2C },
+ { 0x7F, 0x5E, 0x8F, 0x2C },
+ { 0x7F, 0x5E, 0x8F, 0x2C },
+ { 0x7F, 0x5E, 0x8F, 0x2C },
+ { 0x87, 0x56, 0x8F, 0x2C },
+ { 0x87, 0x56, 0x8F, 0x2C },
+ { 0x87, 0x56, 0x8F, 0x2C },
+ { 0x87, 0x4E, 0x8F, 0x2C },
+ { 0x87, 0x4E, 0x8F, 0x2C },
+ { 0x87, 0x4E, 0x8F, 0x2C },
+ { 0x8F, 0x4E, 0x9F, 0x2C },
+ { 0x8F, 0x4E, 0x9F, 0x2C },
+ { 0x8F, 0x4E, 0xAF, 0x2C },
+ { 0x8F, 0x4E, 0xAF, 0x2C },
+ { 0x8F, 0x4E, 0xAF, 0x2C },
+ { 0x97, 0x4E, 0xAF, 0x2C },
+ { 0x97, 0x4E, 0xAF, 0x2C },
+ { 0x97, 0x4E, 0xAB, 0x2C },
+ { 0x97, 0x4E, 0xAB, 0x2C },
+ { 0x97, 0x4E, 0xAB, 0x2C },
+ { 0x9F, 0x4E, 0xAB, 0x2C },
+ { 0x9F, 0x4E, 0xBB, 0x2C },
+ { 0x9F, 0x4E, 0xBB, 0x2C },
+ { 0x9F, 0x4E, 0xBB, 0x2C },
+ { 0x9F, 0x4E, 0xCB, 0x2C },
+ { 0xA7, 0x4E, 0xCB, 0x2C },
+ { 0xA7, 0x4E, 0xCB, 0x2C },
+ { 0xA7, 0x46, 0xCB, 0x2C },
+ { 0xA7, 0x46, 0xCB, 0x2C },
+ { 0xA7, 0x46, 0xCB, 0x2C },
+ { 0xA7, 0x46, 0xDB, 0x2C },
+ { 0xAF, 0x46, 0xDB, 0x2C },
+ { 0xAF, 0x46, 0xEB, 0x2C },
+ { 0xAF, 0x46, 0xEB, 0x2C },
+ { 0xAF, 0x4E, 0xEB, 0x2C },
+ { 0xAE, 0x4E, 0xEB, 0x2C },
+ { 0xAE, 0x4E, 0xEB, 0x2C },
+ { 0xB5, 0x46, 0xFB, 0x2C },
+ { 0xB5, 0x54, 0xFB, 0x2C },
+ { 0xB5, 0x4C, 0xFB, 0x2C },
+ { 0xB5, 0x54, 0xFB, 0x2C },
+ { 0xB5, 0x54, 0xFB, 0x2C },
+ { 0xBD, 0x54, 0xFB, 0x2C },
+ { 0xBD, 0x4C, 0xFB, 0x2C },
+ { 0xBD, 0x4C, 0xFB, 0x2C },
+ { 0xBD, 0x4C, 0xFB, 0x2C },
+ { 0xBD, 0x44, 0xEB, 0x2C },
+ { 0xC5, 0x44, 0xFB, 0x2C },
+ { 0xC5, 0x44, 0xFB, 0x2C },
+ { 0xC5, 0x44, 0xFB, 0x2C },
+ { 0xC5, 0x45, 0x0B, 0x2C },
+ { 0xC5, 0x45, 0x0B, 0x2C },
+ { 0xC5, 0x45, 0x0B, 0x2C },
+ { 0xCD, 0x45, 0x0B, 0x2C },
+ { 0xCD, 0x45, 0x0B, 0x2C },
+ { 0xCD, 0x3D, 0x0B, 0x2C },
+ { 0xCD, 0x3D, 0x0B, 0x2C },
+ { 0xCD, 0x3D, 0x0B, 0x2C },
+ { 0xD5, 0x3D, 0x0B, 0x2C },
+ { 0xD5, 0x3D, 0x0B, 0x2C },
+ { 0xD5, 0x3D, 0x1B, 0x2C },
+ { 0xD5, 0x3D, 0x1B, 0x2C },
+ { 0xD5, 0x3D, 0x1B, 0x2C },
+ { 0xDD, 0x3D, 0x1B, 0x2C },
+ { 0xDD, 0x3D, 0x1B, 0x2C },
+ { 0xDD, 0x35, 0x1B, 0x2C },
+ { 0xDD, 0x35, 0x1B, 0x2C },
+ { 0xDD, 0x35, 0x1B, 0x2C },
+ { 0xE5, 0x35, 0x1B, 0x2C },
+ { 0xE5, 0x35, 0x1B, 0x2C },
+ { 0xE5, 0x2D, 0x1B, 0x2C },
+ { 0xE5, 0x2D, 0x1B, 0x2C },
+ { 0xE5, 0x2D, 0x3B, 0x2C },
+ { 0xED, 0x2D, 0x4B, 0x2C },
+ { 0xED, 0x2D, 0x1B, 0xA8 },
+ { 0xED, 0x2D, 0x1B, 0xAC },
+ { 0xED, 0x2D, 0x17, 0xAC },
+ { 0xED, 0x2D, 0x17, 0xAC },
+ { 0xED, 0x2D, 0x27, 0xAC },
+ { 0xF5, 0x2D, 0x27, 0xAC },
+ { 0xF5, 0x2D, 0x27, 0xAC },
+ { 0xF5, 0x2D, 0x2B, 0xAC },
+ { 0xF5, 0x2D, 0x2B, 0xAC },
+ { 0xF5, 0x2D, 0x2B, 0xAC },
+ { 0xFD, 0x2D, 0x2B, 0xAC },
+ { 0xFD, 0x2B, 0x2B, 0xAC },
+ { 0xFD, 0x2B, 0x2B, 0xAC },
+ { 0xFD, 0x2B, 0x2B, 0xAC },
+ { 0xFD, 0x2B, 0x2B, 0xAC },
+ { 0xFD, 0x23, 0x2B, 0xAC },
+ { 0xFD, 0x23, 0x2B, 0xAC },
+ { 0xFD, 0x23, 0x2B, 0xAC },
+ { 0xFD, 0x21, 0x2B, 0xAC },
+ { 0xFD, 0x21, 0x2B, 0xAC },
+ { 0xFD, 0x29, 0x2B, 0xAC },
+ { 0xFD, 0x29, 0x2B, 0xAC },
+ { 0xFD, 0x29, 0x27, 0xAC },
+ { 0xFD, 0x29, 0x37, 0xAC },
+ { 0xFD, 0x29, 0x23, 0xAC },
+ { 0xFD, 0x29, 0x23, 0xAC },
+ { 0xFD, 0x29, 0x23, 0xAC },
+ { 0xFD, 0x29, 0x23, 0xAC },
+ { 0xFD, 0x21, 0x23, 0xAC },
+ { 0xFD, 0x21, 0x23, 0xAC },
+ { 0xFD, 0x21, 0x23, 0xAC },
+ { 0xFD, 0x21, 0x33, 0xAC },
+ { 0xFD, 0x21, 0x33, 0xAC },
+ { 0xFD, 0x21, 0x33, 0xAC },
+ { 0xFD, 0x21, 0x43, 0xAC },
+ { 0xFD, 0x21, 0x43, 0xAC },
+ { 0xFD, 0x21, 0x43, 0xAC },
+ { 0xFC, 0x21, 0x43, 0xAC },
+ { 0xFC, 0x21, 0x43, 0xAC },
+ { 0xFC, 0x19, 0x43, 0xAC },
+ { 0xFC, 0x19, 0x43, 0xAC },
+ { 0xFC, 0x19, 0x43, 0xAC },
+ { 0xFC, 0x19, 0x43, 0xAC },
+ { 0xFC, 0x19, 0x53, 0xAC },
+ { 0xFC, 0x19, 0x53, 0xAC },
+ { 0xFC, 0x19, 0x53, 0xAC },
+ { 0xFC, 0x19, 0x53, 0xAC },
+ { 0xFC, 0x19, 0x63, 0xAC },
+ { 0xFC, 0x19, 0x63, 0xAC },
+ { 0xFC, 0x19, 0x63, 0xAC },
+ { 0xFC, 0x19, 0x73, 0xAC },
+ { 0xFC, 0x19, 0x73, 0xAC },
+ { 0xFC, 0x19, 0x73, 0xAC },
+ { 0xFC, 0x19, 0x73, 0xAC },
+ { 0xFC, 0x19, 0x73, 0xAC },
+ { 0xFC, 0x19, 0x83, 0xAC },
+ { 0xFC, 0x19, 0x83, 0xAC },
+ { 0xFC, 0x19, 0x83, 0xAC },
+ { 0xFC, 0x19, 0x83, 0xAC },
+ { 0xFC, 0x19, 0x83, 0xAC },
+ { 0xFC, 0x19, 0x93, 0xAC },
+ { 0xFC, 0x19, 0x93, 0xAC },
+ { 0xFC, 0x19, 0x93, 0xAC },
+ { 0xFC, 0x19, 0xA3, 0xAC },
+ { 0xFC, 0x19, 0xA3, 0xAC },
+ { 0xFC, 0x19, 0xB3, 0xAC },
+ { 0xFC, 0x19, 0xB3, 0xAC },
+ { 0xFC, 0x19, 0xB3, 0xAC },
+ { 0xFC, 0x19, 0xB3, 0xAC }
+};
+
+
+/*
+ ******************************************************************************
+ FUNCTION PROTOTYPES
+ ******************************************************************************
+*/
+static void ClearTemplate(sdla_t*);
+static unsigned char InitTemplate(sdla_t*);
+static void InitLineReceiver(sdla_t*);
+
+static void ClearTPSCReg(sdla_t*);
+static void ClearRPSCReg(sdla_t*);
+
+static int WriteTPSCReg(sdla_t*, int, int, unsigned char);
+static unsigned char ReadTPSCReg(sdla_t*, int, int);
+
+static int WriteRPSCReg(sdla_t*, int, int, unsigned char);
+static unsigned char ReadRPSCReg(sdla_t*, int, int);
+
+static void DisableAllChannels(sdla_t*);
+static void EnableAllChannels(sdla_t*);
+static int DisableTxChannel(sdla_t*, int);
+static int DisableRxChannel(sdla_t*, int);
+static int EnableTxChannel(sdla_t*, int);
+static int EnableRxChannel(sdla_t*, int);
+
+static void sdla_te_set_intr(sdla_t*);
+static void sdla_te_tx_intr(sdla_t*);
+static void sdla_te_rx_intr(sdla_t*);
+static void sdla_t1_rx_intr(sdla_t*);
+static void sdla_e1_rx_intr(sdla_t*);
+
+static void sdla_te_set_status(sdla_t*, unsigned long);
+static void sdla_te_enable_timer(sdla_t*, unsigned long);
+
+static int sdla_te_linelb(sdla_t*, unsigned char);
+static int sdla_te_paylb(sdla_t*, unsigned char);
+static int sdla_te_ddlb(sdla_t*, unsigned char);
+static int sdla_te_lb(sdla_t*, unsigned char);
+
+/******************************************************************************
+* FUNCTION DEFINITIONS
+******************************************************************************/
+/******************************************************************************
+** ClearTemplate()
+******************************************************************************/
+static void ClearTemplate(sdla_t* card)
+{
+ int i = 0, j = 0;
+ unsigned int indirect_addr = 0x00;
+
+ for (i = FIRST_UI; i <= LAST_UI; i++){
+ for (j = FIRST_SAMPLE; j <= LAST_SAMPLE; j++){
+ indirect_addr = (j << 3) | i;
+ /* Set up the indirect address */
+ WRITE_REG(REG_XLPG_WAVEFORM_ADDR, indirect_addr);
+ WRITE_REG(REG_XLPG_WAVEFORM_DATA, 0x00);
+ }
+ }
+}
+
+/*
+ ******************************************************************************
+ * InitTemplate()
+ *
+ ******************************************************************************
+ */
+static unsigned char InitTemplate(sdla_t* card)
+{
+ sdla_te_cfg_t* te_cfg = &card->fe_te.te_cfg;
+ int i = 0, j = 0;
+ unsigned char indirect_addr = 0x00, xlpg_scale = 0x00;
+ TX_WAVEFORM* tx_waveform = NULL;
+
+ if (IS_T1(&card->fe_te.te_cfg)){
+ switch (te_cfg->lbo){
+ case WANOPT_T1_LBO_0_DB:
+ tx_waveform = &t1_tx_waveform_lh_0db;
+ xlpg_scale = 0x0C;
+ break;
+ case WANOPT_T1_LBO_75_DB:
+ tx_waveform = &t1_tx_waveform_lh_75db;
+ xlpg_scale = 0x07;
+ break;
+ case WANOPT_T1_LBO_15_DB:
+ tx_waveform = &t1_tx_waveform_lh_15db;
+ xlpg_scale = 0x03;
+ break;
+ case WANOPT_T1_LBO_225_DB:
+ tx_waveform = &t1_tx_waveform_lh_225db;
+ xlpg_scale = 0x02;
+ break;
+ case WANOPT_T1_0_110:
+ tx_waveform = &t1_tx_waveform_sh_110ft;
+ xlpg_scale = 0x0C;
+ break;
+ case WANOPT_T1_110_220:
+ tx_waveform = &t1_tx_waveform_sh_220ft;
+ xlpg_scale = 0x10;
+ break;
+ case WANOPT_T1_220_330:
+ tx_waveform = &t1_tx_waveform_sh_330ft;
+ xlpg_scale = 0x11;
+ break;
+ case WANOPT_T1_330_440:
+ tx_waveform = &t1_tx_waveform_sh_440ft;
+ xlpg_scale = 0x12;
+ break;
+ case WANOPT_T1_440_550:
+ tx_waveform = &t1_tx_waveform_sh_550ft;
+ xlpg_scale = 0x14;
+ break;
+ case WANOPT_T1_550_660:
+ tx_waveform = &t1_tx_waveform_sh_660ft;
+ xlpg_scale = 0x15;
+ break;
+ default:
+ /* Use 0DB as a default value */
+ tx_waveform = &t1_tx_waveform_lh_0db;
+ xlpg_scale = 0x0C;
+ break;
+ }
+ } else {
+ tx_waveform = &e1_tx_waveform_120;
+ xlpg_scale = 0x0C;
+ /*xlpg_scale = 0x0B; */
+ }
+
+ for (i = FIRST_UI; i <= LAST_UI; i++){
+ for (j = FIRST_SAMPLE; j <= LAST_SAMPLE; j++){
+ indirect_addr = (j << 3) | i;
+ /* Set up the indirect address */
+ WRITE_REG(REG_XLPG_WAVEFORM_ADDR, indirect_addr);
+ WRITE_REG(REG_XLPG_WAVEFORM_DATA, (*tx_waveform)[j][i]);
+ }
+ }
+ return xlpg_scale;
+}
+
+/*
+ ******************************************************************************
+ * InitLineReceiver()
+ ******************************************************************************
+ */
+static void InitLineReceiver(sdla_t* card)
+{
+ int ram_addr = 0x00;
+ RLPS_EQUALIZER_RAM *rlps_ram_table = NULL;
+
+ if (IS_E1(&card->fe_te.te_cfg)){
+ rlps_ram_table = e1_rlps_ram_table;
+ }else{
+ if (card->fe_te.te_cfg.high_impedance_mode == WANOPT_YES){
+ log(LOG_INFO, "%s: Setting to High-Impedance Mode!\n",
+ card->devname);
+ rlps_ram_table = t1_rlps_perf_mode_ram_table;
+ }else{
+ rlps_ram_table = t1_rlps_ram_table;
+ }
+ }
+ for (ram_addr = 0; ram_addr <= 255; ram_addr++){
+/* ERRATA VVV */
+ /* Configure a write into the RAM address */
+ WRITE_REG(REG_RLPS_EQ_RWB, BIT_RLPS_EQ_RWB);
+ /* Initiate write into the specified RAM address */
+ WRITE_REG(REG_RLPS_EQ_ADDR, (unsigned char)ram_addr);
+ DELAY(100);
+/* ERRATA ^^^ */
+ /* Write 1st value from conten column */
+ WRITE_REG(REG_RLPS_IND_DATA_1, rlps_ram_table[ram_addr].byte1);
+ /* Write 2st value from conten column */
+ WRITE_REG(REG_RLPS_IND_DATA_2, rlps_ram_table[ram_addr].byte2);
+ /* Write 3st value from conten column */
+ WRITE_REG(REG_RLPS_IND_DATA_3, rlps_ram_table[ram_addr].byte3);
+ /* Write 4st value from conten column */
+ WRITE_REG(REG_RLPS_IND_DATA_4, rlps_ram_table[ram_addr].byte4);
+ /* Configure a write into the RAM address */
+ WRITE_REG(REG_RLPS_EQ_RWB, 0x00);
+ /* Initiate write into the specified RAM address */
+ WRITE_REG(REG_RLPS_EQ_ADDR, (unsigned char)ram_addr);
+/* ERRATA VVV */
+ DELAY(100);
+/* ERRATA ^^^ */
+ }
+}
+
+/*
+ ******************************************************************************
+ * ClearTPSCReg()
+ *
+ * Description: Clear all TPSC indirect register.
+ ******************************************************************************
+ */
+static void ClearTPSCReg(sdla_t* card)
+{
+ int channel = 0;
+ int start_channel = 0, stop_channel = 0;
+
+ if (IS_E1(&card->fe_te.te_cfg)){
+ start_channel = 0;
+ stop_channel = NUM_OF_E1_TIMESLOTS + 1;
+ }else{
+ start_channel = 1;
+ stop_channel = NUM_OF_T1_CHANNELS;
+ }
+
+ for (channel = start_channel; channel <= stop_channel; channel++){
+ WRITE_TPSC_REG(REG_TPSC_DATA_CTRL_BYTE, channel, 0x00);
+ WRITE_TPSC_REG(REG_TPSC_IDLE_CODE_BYTE, channel, 0x00);
+ WRITE_TPSC_REG(REG_TPSC_SIGNALING_BYTE, channel, 0x00);
+ }
+ return;
+}
+
+/*
+ ******************************************************************************
+ * ClearRPSCReg()
+ *
+ * Description: Clear all RPSC indirect register.
+ ******************************************************************************
+ */
+static void ClearRPSCReg(sdla_t* card)
+{
+ int channel = 0;
+ int start_channel = 0, stop_channel = 0;
+
+ if (IS_E1(&card->fe_te.te_cfg)){
+ start_channel = 0;
+ stop_channel = NUM_OF_E1_TIMESLOTS + 1;
+ }else{
+ start_channel = 1;
+ stop_channel = NUM_OF_T1_CHANNELS;
+ }
+
+ for (channel = start_channel; channel <= stop_channel; channel++){
+ WRITE_RPSC_REG(REG_RPSC_DATA_CTRL_BYTE, channel, 0x00);
+ WRITE_RPSC_REG(REG_RPSC_DATA_COND_BYTE, channel, 0x00);
+ WRITE_RPSC_REG(REG_RPSC_SIGNALING_BYTE, channel, 0x00);
+ }
+ return;
+}
+
+/*
+ ******************************************************************************
+ * WriteTPSCReg()
+ *
+ * Description: Write value to TPSC indirect register.
+ * Arguments: card - Pointer to the card structure
+ * reg - Offset in TPSC indirect space.
+ * channel - Channel number.
+ * value - New PMC register value.
+ * Returns: 0 - success, otherwise - error
+ ******************************************************************************
+ */
+static int
+WriteTPSCReg(sdla_t* card, int reg, int channel, unsigned char value)
+{
+ unsigned char temp = 0x00;
+ int i = 0, busy_flag = 0;
+ int err = 0;
+
+ reg += channel;
+ /* Set IND bit to 1 in TPSC to enable indirect access to
+ ** TPSC register */
+ WRITE_REG(REG_TPSC_CFG, BIT_TPSC_IND);
+ busy_flag = 1;
+ for (i = 0; i < MAX_BUSY_READ; i++){
+ temp = READ_REG(REG_TPSC_MICRO_ACCESS_STATUS);
+ if ((temp & BIT_TPSC_BUSY) == 0x0){
+ busy_flag = 0;
+ break;
+ }
+ }
+ if (busy_flag == 1){
+ log(LOG_INFO, "%s: Failed to write to TPSC Reg[%02x]<-%02x!\n",
+ card->devname, reg, value);
+ err = -EBUSY;
+ goto write_tpsc_done;
+ }
+
+ WRITE_REG(REG_TPSC_CHANNEL_INDIRECT_DATA_BUFFER,
+ (unsigned char)value);
+ WRITE_REG(REG_TPSC_CHANNEL_INDIRECT_ADDRESS_CONTROL,
+ (unsigned char)(reg & 0x7F));
+
+ for (i = 0; i < MAX_BUSY_READ; i++){
+ temp = READ_REG(REG_TPSC_MICRO_ACCESS_STATUS);
+ if ((temp & BIT_TPSC_BUSY) == 0x0){
+ err = -EBUSY;
+ goto write_tpsc_done;
+ }
+ }
+ log(LOG_INFO, "%s: Failed to write value to TPSC Reg=%02x, val=%02x.\n",
+ card->devname, reg, value);
+write_tpsc_done:
+ /* Set PCCE bit to 1 in TPSC to enable modifing the TPSC register */
+ WRITE_REG(REG_TPSC_CFG, BIT_TPSC_IND | BIT_TPSC_PCCE);
+ return err;
+}
+
+/*
+ ******************************************************************************
+ * ReadTPSCReg()
+ *
+ * Description: Read value from TPSC indirect register.
+ * Arguments: card - Pointer to the card structure
+ * reg - Offset in TPSC indirect space.
+ * channel - Channel number.
+ * Returns: Returns register value.
+ ******************************************************************************
+ */
+static unsigned char ReadTPSCReg(sdla_t* card, int reg, int channel)
+{
+ unsigned char tmp = 0x00, value = 0x00;
+ int i = 0, busy_flag = 0;
+
+ reg += channel;
+ /* Set IND bit to 1 in TPSC to enable indirect access to
+ ** TPSC register */
+ WRITE_REG(REG_TPSC_CFG, BIT_TPSC_IND);
+ busy_flag = 1;
+ for (i = 0; i < MAX_BUSY_READ; i++){
+ tmp = READ_REG(REG_TPSC_MICRO_ACCESS_STATUS);
+ if ((tmp & BIT_TPSC_BUSY) == 0x0){
+ busy_flag = 0;
+ break;
+ }
+ }
+ if (busy_flag == 1){
+ log(LOG_INFO, "%s: Failed to read value to TPSC Reg=%02x!\n",
+ card->devname, reg);
+ goto read_tpsc_done;
+ }
+
+ WRITE_REG(REG_TPSC_CHANNEL_INDIRECT_ADDRESS_CONTROL,
+ (unsigned char)(reg | 0x80));
+
+ for (i = 0; i < MAX_BUSY_READ; i++){
+ tmp = READ_REG(REG_TPSC_MICRO_ACCESS_STATUS);
+ if ((tmp & BIT_TPSC_BUSY) == 0x0){
+ value = READ_REG(REG_TPSC_CHANNEL_INDIRECT_DATA_BUFFER);
+ goto read_tpsc_done;
+ }
+ }
+ log(LOG_INFO, "%s: Failed to read value to TPSC Reg=%02x.\n",
+ card->devname, reg);
+read_tpsc_done:
+ /* Set PCCE bit to 1 in TPSC to enable modifing the TPSC register */
+ WRITE_REG(REG_TPSC_CFG, BIT_TPSC_IND | BIT_TPSC_PCCE);
+ return value;
+}
+
+/*
+ ******************************************************************************
+ * WriteRPSCReg()
+ *
+ * Description: Write value to RPSC indirect register.
+ * Arguments: card - Pointer to the card structure
+ * reg - Offset in RPSC indirect space.
+ * channel - Channel number.
+ * value - New PMC register value.
+ * Returns: 0-success, otherwise - error
+ ******************************************************************************
+ */
+static int
+WriteRPSCReg(sdla_t* card, int reg, int channel, unsigned char value)
+{
+ unsigned char temp = 0x00;
+ int i = 0, busy_flag = 0;
+ int err = 0;
+
+ reg += channel;
+ /* Set IND bit to 1 in RPSC to enable indirect access to
+ ** RPSC register*/
+ WRITE_REG(REG_RPSC_CFG, BIT_RPSC_IND);
+ busy_flag = 1;
+ for (i = 0; i < MAX_BUSY_READ; i++){
+ temp = READ_REG(REG_RPSC_MICRO_ACCESS_STATUS);
+ if ((temp & BIT_RPSC_BUSY) == 0x0){
+ busy_flag = 0;
+ break;
+ }
+ }
+ if (busy_flag == 1){
+ log(LOG_INFO, "%s: Failed to write to RPSC Reg[%02x]<-%02x!\n",
+ card->devname, reg, value);
+ err = -EBUSY;
+ goto write_rpsc_done;
+ }
+
+ WRITE_REG(REG_RPSC_CHANNEL_INDIRECT_DATA_BUFFER,
+ (unsigned char)value);
+ WRITE_REG(REG_RPSC_CHANNEL_INDIRECT_ADDRESS_CONTROL,
+ (unsigned char)(reg & 0x7F));
+
+ for (i = 0; i < MAX_BUSY_READ; i++){
+ temp = READ_REG(REG_RPSC_MICRO_ACCESS_STATUS);
+ if ((temp & BIT_RPSC_BUSY) == 0x0){
+ err = -EBUSY;
+ goto write_rpsc_done;
+ }
+ }
+ log(LOG_INFO, "%s: Failed to write value to RPSC Reg=%02x, val=%02x.\n",
+ card->devname, reg, value);
+write_rpsc_done:
+ /* Set PCCE bit to 1 in RPSC to enable modifing the RPSC register */
+ WRITE_REG(REG_RPSC_CFG, BIT_RPSC_IND | BIT_RPSC_PCCE);
+ return err;
+}
+
+/*
+ ******************************************************************************
+ * ReadRPSCReg()
+ *
+ * Description: Read value from RPSC indirect register.
+ * Arguments: card - Pointer to the card structure
+ * reg - Offset in RPSC indirect space.
+ * channel - Channel number
+ * Returns: Returns register value.
+ ******************************************************************************
+ */
+static unsigned char ReadRPSCReg(sdla_t* card, int reg, int channel)
+{
+ unsigned char tmp = 0x00, value = 0x00;
+ int i = 0,busy_flag = 0;
+
+ reg += channel;
+ /* Set IND bit to 1 in RPSC to enable indirect access to
+ ** RPSC register*/
+ WRITE_REG(REG_RPSC_CFG, BIT_RPSC_IND);
+ busy_flag = 1;
+ for (i = 0; i < MAX_BUSY_READ; i++){
+ tmp = READ_REG(REG_RPSC_MICRO_ACCESS_STATUS);
+ if ((tmp & BIT_RPSC_BUSY) == 0x0){
+ busy_flag = 0;
+ break;
+ }
+ }
+ if (busy_flag == 1){
+ log(LOG_INFO, "%s: Failed to read value to RPSC Reg=%02x!\n",
+ card->devname, reg);
+ goto read_rpsc_done;
+ }
+
+ WRITE_REG(REG_RPSC_CHANNEL_INDIRECT_ADDRESS_CONTROL,
+ (unsigned char)(reg | 0x80));
+
+ for (i = 0; i < MAX_BUSY_READ; i++) {
+ tmp = READ_REG(REG_RPSC_MICRO_ACCESS_STATUS);
+ if ((tmp & BIT_RPSC_BUSY) == 0x0){
+ value = READ_REG(REG_RPSC_CHANNEL_INDIRECT_DATA_BUFFER);
+ goto read_rpsc_done;
+ }
+ }
+ log(LOG_INFO, "%s: Failed to read value to RPSC Reg=%02x.\n",
+ card->devname, reg);
+read_rpsc_done:
+ /* Set PCCE bit to 1 in RPSC to enable modifing the RPSC register */
+ WRITE_REG(REG_RPSC_CFG, BIT_RPSC_IND | BIT_RPSC_PCCE);
+ return value;
+}
+
+
+/*
+ ******************************************************************************
+ * DisableAllChannels()
+ *
+ * Description: Disable All channels for RX/TX
+ * Arguments: card - Pointer to the card structure.
+ * Returns: none
+ ******************************************************************************
+ */
+static void DisableAllChannels(sdla_t* card)
+{
+ int i = 0;
+
+ if (IS_E1(&card->fe_te.te_cfg)) {
+ DisableTxChannel(card, E1_FRAMING_TIMESLOT);
+ DisableRxChannel(card, E1_FRAMING_TIMESLOT);
+ for (i = 1; i <= NUM_OF_E1_TIMESLOTS; i++){
+ DisableTxChannel(card, i);
+ DisableRxChannel(card, i);
+ }
+ }else{
+ for (i = 1; i <= NUM_OF_T1_CHANNELS; i++){
+ DisableTxChannel(card, i);
+ DisableRxChannel(card, i);
+ }
+ }
+}
+
+/*
+ ******************************************************************************
+ * EnableAllChannels()
+ *
+ * Description: Enable All channels.
+ * Arguments: card - Pointer to the card structure.
+ * Returns: none
+ ******************************************************************************
+ */
+static void EnableAllChannels(sdla_t* card)
+{
+ int i = 0;
+
+ if (IS_E1(&card->fe_te.te_cfg)){
+ int first_ts =
+ (card->fe_te.te_cfg.frame == WANOPT_FR_UNFRAMED) ?
+ 0 : 1;
+
+ DisableTxChannel(card, E1_FRAMING_TIMESLOT);
+ DisableRxChannel(card, E1_FRAMING_TIMESLOT);
+ for (i = first_ts; i <= NUM_OF_E1_TIMESLOTS; i++){
+ EnableTxChannel(card, i);
+ EnableRxChannel(card, i);
+ }
+ }else{
+ for (i = 1; i <= NUM_OF_T1_CHANNELS; i++){
+ EnableTxChannel(card, i);
+ EnableRxChannel(card, i);
+ }
+ }
+}
+
+/*
+ ******************************************************************************
+ * EnableTxChannel()
+ *
+ * Description: Enable Tx for specific channel
+ * Arguments: card - pointer to the card structure
+ * channel - channel number
+ * Returns: 0-success, otherwise-error
+ ******************************************************************************
+ */
+static int EnableTxChannel(sdla_t* card, int channel)
+{
+ sdla_te_cfg_t* te_cfg = &card->fe_te.te_cfg;
+
+ if (te_cfg->lcode == WANOPT_LC_AMI){
+ /* ZCs=1 AMI*/
+ WRITE_TPSC_REG(REG_TPSC_DATA_CTRL_BYTE, channel,
+ (((READ_TPSC_REG(REG_TPSC_DATA_CTRL_BYTE, channel) &
+ MASK_TPSC_DATA_CTRL_BYTE) &
+ ~BIT_TPSC_DATA_CTRL_BYTE_IDLE_DS0) |
+ BIT_TPSC_DATA_CTRL_BYTE_ZCS1));
+ }else{
+ WRITE_TPSC_REG(REG_TPSC_DATA_CTRL_BYTE, channel,
+ ((READ_TPSC_REG(REG_TPSC_DATA_CTRL_BYTE, channel) &
+ MASK_TPSC_DATA_CTRL_BYTE) &
+ ~(BIT_TPSC_DATA_CTRL_BYTE_IDLE_DS0 |
+ BIT_TPSC_DATA_CTRL_BYTE_ZCS1 |
+ BIT_TPSC_DATA_CTRL_BYTE_ZCS0)));
+ }
+
+ if (IS_E1(&card->fe_te.te_cfg)){
+ /* Set SUBS=DS[0]=DS[1]=0x0 - no change to PCM timeslot data */
+ WRITE_TPSC_REG(REG_TPSC_E1_CTRL_BYTE, channel,
+ (READ_TPSC_REG(REG_TPSC_E1_CTRL_BYTE, channel) &
+ ~(BIT_TPSC_E1_CTRL_BYTE_SUBS |
+ BIT_TPSC_E1_CTRL_BYTE_DS0 |
+ BIT_TPSC_E1_CTRL_BYTE_DS1)));
+ }else{
+ WRITE_TPSC_REG(REG_TPSC_SIGNALING_BYTE, channel, 0x00);
+ }
+
+ /* Erase contents of IDLE code byte */
+ WRITE_TPSC_REG(REG_TPSC_IDLE_CODE_BYTE, channel, 0x00);
+
+ return 0;
+}
+/*
+ ******************************************************************************
+ * EnableRxChannel()
+ *
+ * Description: Enable Rx for specific channel
+ * Arguments: card - pointer to the card structure
+ * channel - channel number
+ * Returns: 0-success, otherwise-error
+ ******************************************************************************
+ */
+static int EnableRxChannel(sdla_t* card, int channel)
+{
+ /* Set DTRPC bit to 0 in RPSC */
+ WRITE_RPSC_REG(REG_RPSC_DATA_CTRL_BYTE, channel,
+ ((READ_RPSC_REG(REG_RPSC_DATA_CTRL_BYTE, channel) &
+ MASK_RPSC_DATA_CTRL_BYTE) &
+ ~BIT_RPSC_DATA_CTRL_BYTE_DTRKC));
+ return 0;
+}
+
+/*
+ ******************************************************************************
+ * DisableTxChannel()
+ *
+ * Description: Disable Tx for specific channel
+ * Arguments: card - pointer to the card structure
+ * channel - channel number
+ * Returns: 0-success, otherwise-error
+ ******************************************************************************
+ */
+static int DisableTxChannel(sdla_t* card, int channel)
+{
+ /* Set IDLE_DS0 to 1 for an IDLE code byte will insert and
+ * BTCLK will suppressed
+ */
+ WRITE_TPSC_REG(REG_RPSC_DATA_CTRL_BYTE, channel,
+ ((READ_TPSC_REG(REG_TPSC_DATA_CTRL_BYTE, channel) &
+ MASK_TPSC_DATA_CTRL_BYTE) |
+ BIT_TPSC_DATA_CTRL_BYTE_IDLE_DS0));
+ if (IS_E1(&card->fe_te.te_cfg)){
+ /* Set SUBS=1, DS0=0 - data substitution on - IDLE code
+ ** replaces BTPCM timeslot data */
+ WRITE_TPSC_REG(REG_TPSC_E1_CTRL_BYTE, channel,
+ ((READ_TPSC_REG(REG_TPSC_E1_CTRL_BYTE, channel) &
+ ~BIT_TPSC_E1_CTRL_BYTE_DS0) |
+ BIT_TPSC_E1_CTRL_BYTE_SUBS));
+ }else{
+ WRITE_TPSC_REG(REG_TPSC_SIGNALING_BYTE, channel, 0x00);
+ }
+ /* Erase contents of IDLE code byte */
+ WRITE_TPSC_REG(REG_TPSC_IDLE_CODE_BYTE, channel, 0x55);
+ return 0;
+}
+
+/*
+ ******************************************************************************
+ * DisableRxChannel()
+ *
+ * Description: Disable Rx for specific channel
+ * Arguments: card - pointer to the card structure
+ * channel - channel number
+ * Returns: 0-success, otherwise-error
+ ******************************************************************************
+ */
+static int DisableRxChannel(sdla_t* card, int channel)
+{
+ /* Set DTRPC bit to 1 in RPSC to hold low for the duration of
+ ** the channel */
+ WRITE_RPSC_REG(REG_RPSC_DATA_CTRL_BYTE, channel,
+ ((READ_RPSC_REG(REG_RPSC_DATA_CTRL_BYTE, channel) & MASK_RPSC_DATA_CTRL_BYTE) |
+ BIT_RPSC_DATA_CTRL_BYTE_DTRKC));
+ return 0;
+}
+
+/******************************************************************************
+** sdla_te_defcfg
+**
+** Description: Set default T1 configuration
+******************************************************************************/
+int sdla_te_defcfg(void *pte_cfg)
+{
+ sdla_te_cfg_t *te_cfg = (sdla_te_cfg_t*)pte_cfg;
+
+ te_cfg->media = WANOPT_MEDIA_T1;
+ te_cfg->lcode = WANOPT_LC_B8ZS;
+ te_cfg->frame = WANOPT_FR_ESF;
+ te_cfg->lbo = WANOPT_T1_LBO_0_DB;
+ te_cfg->te_clock = WANOPT_NORMAL_CLK;
+ te_cfg->active_ch = ENABLE_ALL_CHANNELS;
+ te_cfg->high_impedance_mode= WANOPT_NO;
+ return 0;
+}
+
+
+int sdla_te_setcfg(void *pcard, struct ifmedia *ifm)
+{
+ sdla_t *card = (sdla_t*)pcard;
+ sdla_te_cfg_t *te_cfg = (sdla_te_cfg_t*)&card->fe_te.te_cfg;
+
+ switch (ifm->ifm_media){
+ case(IFM_TDM|IFM_TDM_T1):
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Setting T1 media type!\n",
+ card->devname);
+#endif
+ te_cfg->media = WANOPT_MEDIA_T1;
+ te_cfg->lcode = WANOPT_LC_B8ZS;
+ te_cfg->frame = WANOPT_FR_ESF;
+ break;
+ case(IFM_TDM|IFM_TDM_T1_AMI):
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Setting T1 AMI media type!\n",
+ card->devname);
+#endif
+ te_cfg->media = WANOPT_MEDIA_T1;
+ te_cfg->lcode = WANOPT_LC_AMI;
+ te_cfg->frame = WANOPT_FR_ESF;
+ break;
+ case(IFM_TDM|IFM_TDM_E1):
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Setting E1 media type!\n",
+ card->devname);
+#endif
+ te_cfg->media = WANOPT_MEDIA_E1;
+ te_cfg->lcode = WANOPT_LC_HDB3;
+ te_cfg->frame = WANOPT_FR_NCRC4;
+ break;
+ case(IFM_TDM|IFM_TDM_E1_AMI):
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Setting E1 AMI media type!\n",
+ card->devname);
+#endif
+ te_cfg->media = WANOPT_MEDIA_E1;
+ te_cfg->lcode = WANOPT_LC_AMI;
+ te_cfg->frame = WANOPT_FR_NCRC4;
+ break;
+ default:
+ log(LOG_INFO, "%s: Unsupported ifmedia type (%04X)\n",
+ card->devname, ifm->ifm_media);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ ******************************************************************************
+ * sdla_te_settimeslot()
+ *
+ * Description: Set timeslot map
+ ******************************************************************************
+ */
+void sdla_te_settimeslot(void* pcard, unsigned long ts_map)
+{
+ sdla_t *card = (sdla_t*)pcard;
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Setting timeslot map to %08lX\n",
+ card->devname, ts_map);
+#endif
+ card->fe_te.te_cfg.active_ch = ts_map;
+ return;
+}
+
+unsigned long sdla_te_gettimeslot(void* pcard)
+{
+ return ((sdla_t*)pcard)->fe_te.te_cfg.active_ch;
+}
+
+/*
+ ******************************************************************************
+ * sdla_te_config()
+ *
+ * Description: Configure Sangoma TE1 board
+ * Arguments:
+ * Returns: 0 - TE1 configred successfully, otherwise -EINVAL.
+ ******************************************************************************
+ */
+short sdla_te_config(void* card_id)
+{
+ sdla_t* card = (sdla_t*)card_id;
+ sdla_te_cfg_t* te_cfg = &card->fe_te.te_cfg;
+ u_int16_t adapter_type;
+ unsigned char value = 0x00, xlpg_scale = 0x00;
+ int channel_range = (IS_T1(&card->fe_te.te_cfg)) ?
+ NUM_OF_T1_CHANNELS : NUM_OF_E1_TIMESLOTS;
+ int i = 0;
+
+ WAN_ASSERT(card == NULL);
+ WAN_ASSERT(card->write_front_end_reg == NULL);
+ WAN_ASSERT(card->read_front_end_reg == NULL);
+ sdla_getcfg(card->hw, SDLA_ADAPTERTYPE, &adapter_type);
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Setting %s configuration!\n",
+ card->devname,
+ IS_T1(&card->fe_te.te_cfg) ? "T1" : "E1");
+ if (IS_T1(&card->fe_te.te_cfg)){
+ log(LOG_DEBUG, "%s: Line decoding %s\n",
+ card->devname,
+ (te_cfg->lcode == WANOPT_LC_AMI) ? "AMI" : "B8ZS");
+ log(LOG_DEBUG, "%s: Frame type %s\n",
+ card->devname,
+ (te_cfg->frame == WANOPT_FR_ESF) ? "ESF" :
+ (te_cfg->frame == WANOPT_FR_D4) ? "D4" : "Unframed");
+ switch (te_cfg->lbo){
+ case WANOPT_T1_LBO_0_DB:
+ log(LOG_DEBUG, "%s: LBO 0 dB\n", card->devname);
+ break;
+ case WANOPT_T1_LBO_75_DB:
+ log(LOG_DEBUG, "%s: LBO 7.5 dB\n", card->devname);
+ break;
+ case WANOPT_T1_LBO_15_DB:
+ log(LOG_DEBUG, "%s: LBO 15 dB\n", card->devname);
+ break;
+ case WANOPT_T1_LBO_225_DB:
+ log(LOG_DEBUG, "%s: LBO 22.5 dB\n", card->devname);
+ break;
+ case WANOPT_T1_0_110:
+ log(LOG_DEBUG, "%s: LBO 0-110 ft.\n", card->devname);
+ break;
+ case WANOPT_T1_110_220:
+ log(LOG_DEBUG, "%s: LBO 110-220 ft.\n", card->devname);
+ break;
+ case WANOPT_T1_220_330:
+ log(LOG_DEBUG, "%s: LBO 220-330 ft.\n", card->devname);
+ break;
+ case WANOPT_T1_330_440:
+ log(LOG_DEBUG, "%s: LBO 330-440 ft.\n", card->devname);
+ break;
+ case WANOPT_T1_440_550:
+ log(LOG_DEBUG, "%s: LBO 440-550 ft.\n", card->devname);
+ break;
+ case WANOPT_T1_550_660:
+ log(LOG_DEBUG, "%s: LBO 550-660 ft.\n",
+ card->devname);
+ break;
+ }
+ }else{
+ log(LOG_DEBUG, "%s: Line decoding %s\n",
+ card->devname,
+ (te_cfg->lcode == WANOPT_LC_AMI) ? "AMI" : "HDB3");
+ log(LOG_DEBUG, "%s: Frame type %s\n",
+ card->devname,
+ (te_cfg->frame == WANOPT_FR_CRC4) ? "CRC4" :
+ (te_cfg->frame == WANOPT_FR_NCRC4) ? "non-CRC3" :
+ "Unframed");
+ }
+ log(LOG_DEBUG, "%s: Clock mode %s\n",
+ card->devname,
+ (te_cfg->te_clock == WANOPT_NORMAL_CLK) ?
+ "Normal" : "Master");
+#endif
+
+ /* 1. Initiate software reset of the COMET */
+ /* Set RESET=1 to place COMET into RESET */
+ WRITE_REG(REG_RESET, BIT_RESET);
+
+ /* Set RESET=0, disable software reset. COMET in default mode. */
+ WRITE_REG(REG_RESET, 0x0/*~BIT_RESET*/);
+
+ /* 2.Setup the XLPG(Transmit pulse template) to clear the pulse
+ ** template */
+ ClearTemplate(card);
+ xlpg_scale = InitTemplate(card);
+
+ /* Program PMC for T1/E1 mode (Reg 0x00) */
+ if (IS_E1(&card->fe_te.te_cfg)){
+ if (adapter_type & A101_ADPTR_T1E1_MASK){
+ WRITE_REG(REG_GLOBAL_CFG,
+ BIT_GLOBAL_TRKEN | BIT_GLOBAL_PIO_OE |
+ BIT_GLOBAL_E1);
+ }else{
+ WRITE_REG(REG_GLOBAL_CFG,
+ BIT_GLOBAL_PIO_OE | BIT_GLOBAL_E1);
+ }
+ }else{
+ if (adapter_type & A101_ADPTR_T1E1_MASK){
+ WRITE_REG(REG_GLOBAL_CFG,
+ BIT_GLOBAL_TRKEN | BIT_GLOBAL_PIO_OE);
+ }
+ }
+
+ /* Set SCALE[4-0] value in XLPG Line driver Configuration (Reg. 0xF0) */
+ WRITE_REG(REG_XLPG_LINE_CFG, xlpg_scale);
+
+ /* Set system clock and XCLK (Reg 0xD6) */
+ if (IS_T1(&card->fe_te.te_cfg)){
+ WRITE_REG(REG_CSU_CFG, BIT_CSU_MODE0);
+ /*WRITE_REG(REG_CSU_CFG,
+ ** BIT_CSU_MODE2 | BIT_CSU_MODE1 | BIT_CSU_MODE0); */
+ }else{
+ WRITE_REG(REG_CSU_CFG, 0x00);
+ }
+
+ /* Set Line decoding (Reg. 0x10) */
+ if (te_cfg->lcode == WANOPT_LC_AMI){
+ WRITE_REG(REG_CDRC_CFG, BIT_CDRC_CFG_AMI);
+ }else{
+ WRITE_REG(REG_CDRC_CFG, 0x00);
+ }
+
+ /* Program the RX-ELST/TX-ELST for the appropriate mode
+ ** (Reg 0x1C, 0x20)*/
+ if (IS_E1(&card->fe_te.te_cfg)) {
+ WRITE_REG(REG_RX_ELST_CFG, BIT_RX_ELST_IR | BIT_RX_ELST_OR);
+ WRITE_REG(REG_TX_ELST_CFG, BIT_TX_ELST_IR | BIT_RX_ELST_OR);
+ }else{
+ WRITE_REG(REG_RX_ELST_CFG, 0x00);
+ WRITE_REG(REG_TX_ELST_CFG, 0x00);
+ }
+
+ value = 0x00;
+ if (IS_E1(&card->fe_te.te_cfg)){
+ /* Program the trasmitter framing and line decoding
+ ** (Reg. 0x80) */
+ if (te_cfg->lcode == WANOPT_LC_AMI){
+ value |= BIT_E1_TRAN_AMI;
+ }
+ if (te_cfg->frame == WANOPT_FR_CRC4){
+ value |= BIT_E1_TRAN_GENCRC;
+ }else if (te_cfg->frame == WANOPT_FR_UNFRAMED){
+ value |= BIT_E1_TRAN_FDIS;
+ }
+ /* E1 TRAN Configuration (Reg 0x80) */
+ WRITE_REG(REG_E1_TRAN_CFG, value);
+ /* Configure the receive framer (Reg 0x90) */
+ value = 0x00;
+ if (te_cfg->frame == WANOPT_FR_CRC4){
+ value |=
+ (BIT_E1_FRMR_CRCEN |
+ BIT_E1_FRMR_CASDIS |
+ BIT_E1_FRMR_REFCRCEN);
+ }else if (te_cfg->frame == WANOPT_FR_NCRC4){
+ value |= BIT_E1_FRMR_CASDIS;
+ }
+ WRITE_REG(REG_E1_FRMR_CFG, value);
+ }else{
+ /* Set framing format & line decoding for transmitter
+ ** (Reg 0x54) */
+ if (te_cfg->lcode == WANOPT_LC_B8ZS){
+ value |= BIT_T1_XBAS_B8ZS;
+ }else{
+ value |= BIT_T1_XBAS_ZCS0;
+ }
+ if (te_cfg->frame == WANOPT_FR_ESF){
+ value |= BIT_T1_XBAS_ESF;
+ }
+ WRITE_REG(REG_T1_XBAS_CFG, value);
+
+ /* Program framing format for receiving (Reg. 0x48) */
+ value = 0x00;
+ if (te_cfg->frame == WANOPT_FR_ESF){
+ value = BIT_T1_FRMR_ESF | BIT_T1_FRMR_ESFFA;
+ }
+ WRITE_REG(REG_T1_FRMR_CFG, value);
+
+ /* Program the transmitter framing format and line deconding
+ ** (Reg. 0x60) */
+ value = 0x00;
+ if (te_cfg->frame == WANOPT_FR_ESF){
+ value = BIT_T1_ALMI_CFG_ESF;
+ }
+ WRITE_REG(REG_T1_ALMI_CFG, value);
+ }
+
+ /* Configure the SIGX configuration register */
+ if (IS_E1(&card->fe_te.te_cfg)){
+ WRITE_REG(REG_SIGX_CFG, 0x00);
+ }else{
+ value = READ_REG(REG_SIGX_CFG);
+ if (te_cfg->frame == WANOPT_FR_ESF){
+ value |= BIT_SIGX_ESF;
+ }
+ WRITE_REG(REG_SIGX_CFG, value);
+ }
+ /* Program the BTIF for the frame pulse mode */
+ value = 0x00;
+ if (IS_E1(&card->fe_te.te_cfg)){
+ value |= BIT_BTIF_RATE0;
+ }
+ if (te_cfg->lcode == WANOPT_LC_AMI){
+ value |= BIT_BTIF_NXDS0_0;
+ }else if (te_cfg->frame != WANOPT_FR_UNFRAMED){
+ value |= BIT_BTIF_NXDS0_1;
+ }
+
+ if (adapter_type & A101_ADPTR_T1E1_MASK){
+ value |= (BIT_BTIF_CMODE | BIT_BTIF_DE | BIT_BTIF_FE);
+ }
+ WRITE_REG(REG_BTIF_CFG, value);
+ /* Set the type of frame pulse on the backplane */
+ value = 0x00;
+
+ if (adapter_type & A101_ADPTR_T1E1_MASK){
+ value = BIT_BTIF_FPMODE;
+ }
+ WRITE_REG(REG_BTIF_FR_PULSE_CFG, value);
+
+ /* Program the BRIF for the frame pulse mode */
+ value = 0x00;
+ if (IS_E1(&card->fe_te.te_cfg)){
+ value |= BIT_BRIF_RATE0;
+ }
+ if (te_cfg->lcode == WANOPT_LC_AMI){
+ value |= BIT_BRIF_NXDS0_0;
+ }else if (te_cfg->frame != WANOPT_FR_UNFRAMED){
+ value |= BIT_BRIF_NXDS0_1;
+ }
+ if (adapter_type & A101_ADPTR_T1E1_MASK){
+ value |= BIT_BRIF_CMODE;
+ }
+ WRITE_REG(REG_BRIF_CFG, value);
+ /* Set the type of frame pulse on the backplane */
+ value = 0x00;
+
+ if (adapter_type & A101_ADPTR_T1E1_MASK){
+ value = BIT_BRIF_FPMODE;
+ }
+ WRITE_REG(REG_BRIF_FR_PULSE_CFG, value);
+ /* Program the data integraty checking on the BRIF */
+ WRITE_REG(REG_BRIF_DATA_CFG, BIT_BRIF_DATA_TRI_0);
+
+ /* Set TJAT FIFO output clock signal (Reg 0x06) */
+ if (te_cfg->te_clock == WANOPT_NORMAL_CLK){
+ WRITE_REG(REG_TX_TIMING_OPT, BIT_TX_PLLREF1 | BIT_TX_TXELSTBYP);
+ }else{
+ WRITE_REG(REG_TX_TIMING_OPT,
+ BIT_TX_PLLREF1 | BIT_TX_PLLREF0 | BIT_TX_TXELSTBYP);
+ }
+
+ /* Set long or short and enable the equalizer (Reg 0xF8) */
+ WRITE_REG(REG_RLPS_CFG_STATUS, BIT_RLPS_CFG_STATUS_LONGE);
+
+ /* Select ALOS Detection and Clearance Thresholds (Reg 0xF9) */
+ /* NC: Aug 20 2003:
+ * Set the correct ALSO Detection/Clearance tresholds
+ * for T1/E1 lines, to get rid of false ALOS alarms.
+ *
+ * Original incorrect value set was 0x00, for both T1/E1 */
+ if (IS_E1(&card->fe_te.te_cfg)){
+ WRITE_REG(REG_RLPS_ALOS_DET_CLR_THR,
+ BIT_RLPS_ALOS_DET_THR_2|
+ BIT_RLPS_ALOS_DET_THR_1|
+ BIT_RLPS_ALOS_DET_THR_0);
+ }else{
+ WRITE_REG(REG_RLPS_ALOS_DET_CLR_THR,
+ BIT_RLPS_ALOS_CLR_THR_2|
+ BIT_RLPS_ALOS_CLR_THR_0|
+ BIT_RLPS_ALOS_DET_THR_2|
+ BIT_RLPS_ALOS_DET_THR_0);
+ }
+
+ /* Select ALOS Detection period to set the ALOS alarm (Reg 0xFA) */
+ WRITE_REG(REG_RLPS_ALOS_DET_PER, REG_RLPS_ALOS_DET_PER_0);
+ /* Select ALOS Clearance period to clear the ALOS alarm (Reg 0xFB) */
+ WRITE_REG(REG_RLPS_ALOS_CLR_PER, BIT_RLPS_ALOS_CLR_PER_0);
+ /* Program to 0x00 to initiate a microprocessor access to RAM
+ ** (Reg 0xFC) */
+/* ERRATA WRITE_REG(REG_RLPS_EQ_ADDR, 0x00); */
+ /* Write the value 0x80 to this register to select a write to the RAM
+ ** (Reg 0xFD) */
+/* ERRATA WRITE_REG(REG_RLPS_EQ_RWB, BIT_RLPS_EQ_RWB); */
+ /* Program this register to 0x00 to reset the pointer to the RAM
+ ** (Reg 0xFE) */
+ WRITE_REG(REG_RLPS_EQ_STATUS, 0x00);
+ /* Configure the Recive line Equalizer (Reg 0xFF) */
+ WRITE_REG(REG_RLPS_EQ_CFG,
+ BIT_RLPS_EQ_RESERVED | BIT_RLPS_EQ_FREQ_1 | BIT_RLPS_EQ_FREQ_0);
+
+ /* Configure the TJAT FIFO (Reg 0x1B) */
+ WRITE_REG(REG_TJAT_CFG, BIT_TJAT_CENT);
+
+ /* Configure the RJAT FIFO (Reg 0x17) */
+ WRITE_REG(REG_RJAT_CFG, BIT_RJAT_CENT);
+ /* Program Receive Options (Reg 0x02) */
+ if (te_cfg->frame == WANOPT_FR_UNFRAMED){
+ WRITE_REG(REG_RECEIVE_OPT, BIT_RECEIVE_OPT_UNF);
+ }else{
+ WRITE_REG(REG_RECEIVE_OPT, 0x00);
+ }
+
+ /* Configure XLPG Analog Test Positive control (Reg 0xF4) */
+ WRITE_REG(REG_XLPG_TPC, BIT_XLPG_TPC_0);
+ /* Configure XLPG Analog Test Negative control (Reg 0xF5) */
+ WRITE_REG(REG_XLPG_TNC, BIT_XLPG_TNC_0);
+
+ /* Program the RLPS Equalizer Voltage (Reg 0xDC) */
+ if (IS_E1(&card->fe_te.te_cfg)){
+ WRITE_REG(REG_EQ_VREF, 0x34);
+ }else{
+ WRITE_REG(REG_EQ_VREF, 0x2C);
+ }
+ WRITE_REG(REG_RLPS_FUSE_CTRL_STAT, 0x00);
+
+/* ERRATA WRITE_REG(REG_RLPS_FUSE_CTRL_STAT, 0x00);*/
+/* ERRAT VVV */
+ WRITE_REG(0xF4, 0x01);
+ WRITE_REG(0xF4, 0x01);
+ value = READ_REG(0xF4) & 0xFE;
+ WRITE_REG(0xF4, value);
+
+ WRITE_REG(0xF5, 0x01);
+ WRITE_REG(0xF5, 0x01);
+ value = READ_REG(0xF5) & 0xFE;
+ WRITE_REG(0xF5, value);
+
+ WRITE_REG(0xF6, 0x01);
+/* ERRATA ^^^ */
+
+ InitLineReceiver(card);
+
+ ClearRPSCReg(card);
+ ClearTPSCReg(card);
+
+
+ DisableAllChannels(card);
+ if (te_cfg->active_ch == ENABLE_ALL_CHANNELS){
+#if defined(DEBUG_INIT)
+ log(LOG_DEBUG, "%s: All channels enabled\n", card->devname);
+#endif
+ EnableAllChannels(card);
+ }else{
+ for (i = 1; i <= channel_range; i++){
+ if (te_cfg->active_ch & (1 << (i - 1))){
+#if defined(DEBUG_INIT)
+ log(LOG_DEBUG, "%s: Enable channel %d\n",
+ card->devname, i);
+#endif
+ EnableTxChannel(card, i);
+ EnableRxChannel(card, i);
+ }
+ }
+ }
+
+ /* Initialize and start T1/E1 timer */
+ card->fe_te.te_timer_cmd = TE_SET_INTR;
+ bit_clear((u_int8_t*)&card->fe_te.te_critical,TE_TIMER_KILL);
+ timeout_set(&card->fe_te.te_timer, sdla_te_timer, (void*)card);
+ sdla_te_enable_timer(card, INTR_TE1_TIMER);
+
+ bit_set((u_int8_t*)&card->fe_te.te_critical, TE_CONFIGURED);
+
+ return 0;
+}
+
+/*
+ ******************************************************************************
+ * sdla_te_set_intr()
+ *
+ * Description: Enable T1/E1 interrupts.
+ ******************************************************************************
+ */
+static void sdla_te_set_intr(sdla_t* card)
+{
+
+ /* Enable LOS interrupt */
+ /* WRITE_REG(REG_CDRC_INT_EN, BIT_CDRC_INT_EN_LOSE);*/
+ /* Enable ALOS interrupt */
+ WRITE_REG(REG_RLPS_CFG_STATUS,
+ READ_REG(REG_RLPS_CFG_STATUS) | BIT_RLPS_CFG_STATUS_ALOSE);
+ if (IS_T1(&card->fe_te.te_cfg)){
+ /* Enable RBOC interrupt */
+ WRITE_REG(REG_T1_RBOC_ENABLE,
+ BIT_T1_RBOC_ENABLE_IDLE |
+ BIT_T1_RBOC_ENABLE_BOCE);
+ /* Enable interrupt on RED, AIS, YEL alarms */
+ WRITE_REG(REG_T1_ALMI_INT_EN,
+ BIT_T1_ALMI_INT_EN_REDE |
+ BIT_T1_ALMI_INT_EN_AISE |
+ BIT_T1_ALMI_INT_EN_YELE);
+ /* Enable interrupt on OOF alarm */
+ /*WRITE_REG(REG_T1_FRMR_INT_EN, BIT_T1_FRMR_INT_EN_INFRE);*/
+ }else{
+ /* Enable interrupt on RED, AIS alarms */
+ WRITE_REG(REG_E1_FRMR_M_A_INT_EN,
+ BIT_E1_FRMR_M_A_INT_EN_REDE |
+ BIT_E1_FRMR_M_A_INT_EN_AISE);
+ /* Enable OOF Interrupt */
+ /*WRITE_REG(REG_E1_FRMR_FRM_STAT_INT_EN,
+ BIT_E1_FRMR_FRM_STAT_INT_EN_OOFE);*/
+ }
+
+#if 0
+ if (card->te_signaling_config == NULL){
+ /* Enable SIGE and COSS */
+ /* log(LOG_INFO,"%s: Enable SIGX interrupt\n",card->devname);*/
+ WRITE_REG(REG_SIGX_CFG,
+ READ_REG(REG_SIGX_CFG) | BIT_SIGX_SIGE);
+ WRITE_REG(REG_SIGX_CFG,
+ READ_REG(REG_SIGX_CFG) | BIT_SIGX_COSS);
+ }
+#endif
+ /* Initialize T1/E1 timer */
+ bit_clear((u_int8_t*)&card->fe_te.te_critical,TE_TIMER_KILL);
+ /* Start T1/E1 timer */
+ card->fe_te.te_timer_cmd = TE_LINKDOWN_TIMER;
+ sdla_te_enable_timer(card, POLLING_TE1_TIMER);
+ return;
+}
+
+/*
+ ******************************************************************************
+ * sdla_te_unconfig()
+ *
+ * Description: T1/E1 unconfig.
+ ******************************************************************************
+ */
+void sdla_te_unconfig(void* card_id)
+{
+ sdla_t* card = (sdla_t*)card_id;
+
+ if (!bit_test((u_int8_t*)&card->fe_te.te_critical, TE_CONFIGURED)){
+ return;
+ }
+
+ bit_clear((u_int8_t*)&card->fe_te.te_critical, TE_CONFIGURED);
+ bit_set((u_int8_t*)&card->fe_te.te_critical, TE_TIMER_KILL);
+
+ timeout_del(&card->fe_te.te_timer);
+ return;
+}
+
+/*
+ ******************************************************************************
+ * sdla_te_set_status()
+ *
+ * Description: Set T1/E1 status. Enable OOF and LCV interrupt (if status
+ * changed to disconnected.
+ ******************************************************************************
+ */
+static void sdla_te_set_status(sdla_t* card, unsigned long alarms)
+{
+
+ if (IS_T1(&card->fe_te.te_cfg)){
+ if (IS_T1_ALARM(alarms)){
+ if (card->front_end_status != FE_DISCONNECTED){
+ log(LOG_INFO, "%s: T1 disconnected!\n",
+ card->devname);
+ card->front_end_status = FE_DISCONNECTED;
+ }
+ }else{
+ if (card->front_end_status != FE_CONNECTED){
+ log(LOG_INFO, "%s: T1 connected!\n",
+ card->devname);
+ card->front_end_status = FE_CONNECTED;
+ }
+ }
+ }else{
+ if (IS_E1_ALARM(alarms)){
+ if (!bit_test((u_int8_t*)&card->fe_te.te_critical,
+ TE_TIMER_RUNNING)){
+ card->fe_te.te_timer_cmd = TE_LINKDOWN_TIMER;
+ sdla_te_enable_timer(card, POLLING_TE1_TIMER);
+ }
+ if (card->front_end_status != FE_DISCONNECTED){
+ log(LOG_INFO, "%s: E1 disconnected!\n",
+ card->devname);
+ card->front_end_status = FE_DISCONNECTED;
+ }
+ }else{
+ if (card->front_end_status != FE_CONNECTED){
+ log(LOG_INFO, "%s: E1 connected!\n",
+ card->devname);
+ card->front_end_status = FE_CONNECTED;
+ }
+ }
+ }
+#if 0
+ if (card->te_report_alarms){
+ card->te_report_alarms(card, alarms);
+ }
+#endif
+
+#if 0
+ if (card->front_end_status == FE_CONNECTED){
+ WRITE_REG(REG_CDRC_INT_EN,
+ (READ_REG(REG_CDRC_INT_EN) | BIT_CDRC_INT_EN_LOSE));
+ }else{
+ WRITE_REG(REG_CDRC_INT_EN,
+ (READ_REG(REG_CDRC_INT_EN) & ~BIT_CDRC_INT_EN_LOSE));
+ }
+#endif
+
+ return;
+}
+
+/*
+ ******************************************************************************
+ * ReadAlarmStatus()
+ *
+ * Description: Read Alram Status for T1/E1 modes.
+ * Arguments:
+ * Returns: bit 0 - ALOS (E1/T1)
+ * bit 1 - LOS (E1/T1)
+ * bit 2 - ALTLOS (E1/T1)
+ * bit 3 - OOF (E1/T1)
+ * bit 4 - RED (E1/T1)
+ * bit 5 - AIS (E1/T1)
+ * bit 6 - OOSMF (E1)
+ * bit 7 - OOCMF (E1)
+ * bit 8 - OOOF (E1)
+ * bit 9 - RAI (E1)
+ * bit A - YEL (T1)
+ ******************************************************************************
+ */
+unsigned long sdla_te_alarm(void* card_id, int manual_update)
+{
+ sdla_t* card = (sdla_t*)card_id;
+ unsigned long status = 0x00;
+
+ WAN_ASSERT(card->write_front_end_reg == NULL);
+ WAN_ASSERT(card->read_front_end_reg == NULL);
+ /* Check common alarm for E1 and T1 configuration
+ * 1. ALOS alarm
+ * Reg 0xFA
+ * Reg 0xF8 (ALOSI = 1)
+ */
+ if (READ_REG(REG_RLPS_ALOS_DET_PER) &&
+ (READ_REG(REG_RLPS_CFG_STATUS) & BIT_RLPS_CFG_STATUS_ALOSV)){
+ status |= BIT_ALOS_ALARM;
+ }
+
+ /* 2. LOS alarm
+ * Reg 0x10
+ * Reg 0xF8 (ALOSI = 1)
+ */
+ if ((READ_REG(REG_CDRC_CFG) & (BIT_CDRC_CFG_LOS0|BIT_CDRC_CFG_LOS1)) &&
+ (READ_REG(REG_CDRC_INT_STATUS) & BIT_CDRC_INT_STATUS_LOSV)){
+ status |= BIT_LOS_ALARM;
+ }
+
+ /* 3. ALTLOS alarm ??????????????????
+ * Reg 0x13
+ */
+ if (READ_REG(REG_ALTLOS_STATUS) & BIT_ALTLOS_STATUS_ALTLOS){
+ status |= BIT_ALTLOS_ALARM;
+ }
+
+ /* Check specific E1 and T1 alarms */
+ if (IS_E1(&card->fe_te.te_cfg)){
+ /* 4. OOF alarm */
+ if (READ_REG(REG_E1_FRMR_FR_STATUS) &
+ BIT_E1_FRMR_FR_STATUS_OOFV){
+ status |= BIT_OOF_ALARM;
+ }
+ /* 5. OOSMF alarm */
+ if (READ_REG(REG_E1_FRMR_FR_STATUS) &
+ BIT_E1_FRMR_FR_STATUS_OOSMFV){
+ status |= BIT_OOSMF_ALARM;
+ }
+ /* 6. OOCMF alarm */
+ if (READ_REG(REG_E1_FRMR_FR_STATUS) &
+ BIT_E1_FRMR_FR_STATUS_OOCMFV){
+ status |= BIT_OOCMF_ALARM;
+ }
+ /* 7. OOOF alarm */
+ if (READ_REG(REG_E1_FRMR_FR_STATUS) &
+ BIT_E1_FRMR_FR_STATUS_OOOFV){
+ status |= BIT_OOOF_ALARM;
+ }
+ /* 8. RAI alarm */
+ if (READ_REG(REG_E1_FRMR_MAINT_STATUS) &
+ BIT_E1_FRMR_MAINT_STATUS_RAIV){
+ status |= BIT_RAI_ALARM;
+ }
+ /* 9. RED alarm
+ * Reg 0x97 (REDD)
+ */
+ if (READ_REG(REG_E1_FRMR_MAINT_STATUS) &
+ BIT_E1_FRMR_MAINT_STATUS_RED){
+ status |= BIT_RED_ALARM;
+ }
+ /* 10. AIS alarm
+ * Reg 0x91 (AISC)
+ * Reg 0x97 (AIS)
+ */
+ if ((READ_REG(REG_E1_FRMR_MAINT_OPT) &
+ BIT_E1_FRMR_MAINT_OPT_AISC) &&
+ (READ_REG(REG_E1_FRMR_MAINT_STATUS) &
+ BIT_E1_FRMR_MAINT_STATUS_AIS)){
+ status |= BIT_AIS_ALARM;
+ }
+ } else {
+ /* 4. OOF alarm
+ * Reg 0x4A (INFR=0 T1 mode)
+ */
+ if (!(READ_REG(REG_T1_FRMR_INT_STATUS) &
+ BIT_T1_FRMR_INT_STATUS_INFR)){
+ status |= BIT_OOF_ALARM;
+ }
+ /* 5. AIS alarm
+ * Reg 0x62 (AIS)
+ * Reg 0x63 (AISD)
+ */
+ if ((READ_REG(REG_T1_ALMI_INT_STATUS) &
+ BIT_T1_ALMI_INT_STATUS_AIS) &&
+ (READ_REG(REG_T1_ALMI_DET_STATUS) &
+ BIT_T1_ALMI_DET_STATUS_AISD)){
+ status |= BIT_AIS_ALARM;
+ }
+ /* 6. RED alarm
+ * Reg 0x63 (REDD)
+ */
+ if (READ_REG(REG_T1_ALMI_DET_STATUS) &
+ BIT_T1_ALMI_DET_STATUS_REDD){
+ status |= BIT_RED_ALARM;
+ }
+ /* 7. YEL alarm
+ * Reg 0x62 (YEL)
+ * Reg 0x63 (YELD)
+ */
+ if ((READ_REG(REG_T1_ALMI_INT_STATUS) &
+ BIT_T1_ALMI_INT_STATUS_YEL) &&
+ (READ_REG(REG_T1_ALMI_DET_STATUS) &
+ BIT_T1_ALMI_DET_STATUS_YELD)){
+ status |= BIT_YEL_ALARM;
+ }
+ }
+ if (manual_update){
+ sdla_te_set_status(card, status);
+ }
+ return status;
+}
+
+
+/*
+ ******************************************************************************
+ * sdla_te_pmon()
+ *
+ * Description: Read PMC performance monitoring counters
+ ******************************************************************************
+ */
+void sdla_te_pmon(void* card_id)
+{
+ sdla_t* card = (sdla_t*)card_id;
+ pmc_pmon_t* pmon = &card->fe_te.te_pmon;
+
+ WAN_ASSERT1(card->write_front_end_reg == NULL);
+ WAN_ASSERT1(card->read_front_end_reg == NULL);
+ /* Update PMON counters */
+ WRITE_REG(REG_PMON_BIT_ERROR, 0x00);
+ /* Framing bit for E1/T1 */
+ pmon->frm_bit_error +=
+ READ_REG(REG_PMON_BIT_ERROR) & BITS_PMON_BIT_ERROR;
+
+ /* OOF Error for T1 or Far End Block Error for E1 */
+ pmon->oof_errors +=
+ ((READ_REG(REG_PMON_OOF_FEB_MSB_ERROR) &
+ BITS_PMON_OOF_FEB_MSB_ERROR) << 8) |
+ READ_REG(REG_PMON_OOF_FEB_LSB_ERROR);
+
+ /* Bit Error for T1 or CRC Error for E1 */
+ pmon->bit_errors +=
+ ((READ_REG(REG_PMON_BIT_CRC_MSB_ERROR) &
+ BITS_PMON_BIT_CRC_MSB_ERROR) << 8) |
+ READ_REG(REG_PMON_BIT_CRC_LSB_ERROR);
+
+ /* LCV Error for E1/T1 */
+ pmon->lcv +=
+ ((READ_REG(REG_PMON_LCV_MSB_COUNT) &
+ BITS_PMON_LCV_MSB_COUNT) << 8) |
+ READ_REG(REG_PMON_LCV_LSB_COUNT);
+ return;
+}
+
+/*
+ ******************************************************************************
+ * sdla_flush_te1_pmon()
+ *
+ * Description: Flush PMC performance monitoring counters
+ ******************************************************************************
+ */
+void sdla_flush_te1_pmon(void* card_id)
+{
+ sdla_t* card = (sdla_t*)card_id;
+ pmc_pmon_t* pmon = &card->fe_te.te_pmon;
+
+ pmon->pmon1 = 0;
+ pmon->pmon2 = 0;
+ pmon->pmon3 = 0;
+ pmon->pmon4 = 0;
+
+ return;
+}
+
+/*
+ ******************************************************************************
+ * SetLoopBackChannel()
+ *
+ * Description:
+ * Arguments:
+ * Returns:
+ ******************************************************************************
+ */
+static int SetLoopBackChannel(sdla_t* card, int channel, unsigned char mode)
+{
+ /* Set IND bit to 1 in TPSC to enable indirect access to TPSC
+ ** register */
+ WRITE_REG(REG_TPSC_CFG, BIT_TPSC_IND);
+
+ /* Set LOOP to 1 for an IDLE code byte (the transmit data is
+ * overwritten with the corresponding channel data from the receive
+ * line. */
+ if (mode == LINELB_ACTIVATE_CODE){
+ WRITE_TPSC_REG(REG_TPSC_DATA_CTRL_BYTE, channel,
+ ((READ_TPSC_REG(REG_TPSC_DATA_CTRL_BYTE, channel) &
+ MASK_TPSC_DATA_CTRL_BYTE) |
+ BIT_TPSC_DATA_CTRL_BYTE_LOOP));
+ }else{
+ WRITE_TPSC_REG(REG_TPSC_DATA_CTRL_BYTE, channel,
+ ((READ_TPSC_REG(REG_TPSC_DATA_CTRL_BYTE, channel) &
+ MASK_TPSC_DATA_CTRL_BYTE) &
+ ~BIT_TPSC_DATA_CTRL_BYTE_LOOP));
+ }
+
+ /* Set PCCE bit to 1 in TPSC to enable modifing the TPSC register */
+ WRITE_REG(REG_TPSC_CFG,
+ ((READ_REG(REG_TPSC_CFG) & MASK_TPSC_CFG) | BIT_TPSC_PCCE));
+
+ return 0;
+}
+
+/*
+ ******************************************************************************
+ * sdla_te_intr()
+ *
+ * Description: Check interrupt type.
+ * Arguments: card - pointer to device structure.
+ * Returns: None.
+ ******************************************************************************
+ */
+void sdla_te_intr(void* arg)
+{
+ sdla_t* card = (sdla_t*)arg;
+
+ WAN_ASSERT1(card->write_front_end_reg == NULL);
+ WAN_ASSERT1(card->read_front_end_reg == NULL);
+ sdla_te_tx_intr(card);
+ sdla_te_rx_intr(card);
+ sdla_te_set_status(card, card->fe_te.te_alarm);
+}
+
+/*
+ ******************************************************************************
+ * sdla_te_tx_intr()
+ *
+ * Description: Read tx interrupt.
+ * Arguments: card - pointer to device structure.
+ * Returns: None.
+ ******************************************************************************
+ */
+static void sdla_te_tx_intr(sdla_t* card)
+{
+ unsigned char intr_src1 = 0x00, intr_src2 = 0x00, intr_src3 = 0x00;
+
+ intr_src1 = READ_REG(REG_INT_SRC_1);
+ intr_src2 = READ_REG(REG_INT_SRC_2);
+ intr_src3 = READ_REG(REG_INT_SRC_3);
+
+ if (intr_src1 == 0 && intr_src2 == 0 && intr_src3 == 0){
+ log(LOG_DEBUG, "%s: Unknown %s interrupt!\n",
+ card->devname,
+ IS_T1(&card->fe_te.te_cfg) ? "T1" : "E1");
+ }
+ if (!(intr_src1 & BITS_TX_INT_SRC_1 ||
+ intr_src2 & BITS_TX_INT_SRC_2 ||
+ intr_src3 & BITS_TX_INT_SRC_3)){
+ return;
+ }
+
+#if 0
+ if (intr_src1 & BIT_INT_SRC_1_TJAT){
+ }
+ if (intr_src1 & BIT_INT_SRC_1_APRM){
+ }
+ if (intr_src2 & BIT_INT_SRC_2_TX_ELST){
+ }
+ if (intr_src2 & BIT_INT_SRC_2_TDPR_1){
+ }
+ if (intr_src2 & BIT_INT_SRC_2_TDPR_2){
+ }
+ if (intr_src2 & BIT_INT_SRC_2_TDPR_3){
+ }
+ if (intr_src3 & BIT_INT_SRC_3_TRAN){
+ }
+ if (intr_src3 & BIT_INT_SRC_3_XPDE){
+ }
+ if (intr_src3 & BIT_INT_SRC_3_BTIF){
+ }
+#endif
+ return;
+}
+
+
+/*
+ ******************************************************************************
+ * sdla_te_rx_intr()
+ *
+ * Description: Read rx interrupt.
+ * Arguments: card - pointer to device structure.
+ * Returns: None.
+ ******************************************************************************
+ */
+static void sdla_te_rx_intr(sdla_t* card)
+{
+ if (IS_T1(&card->fe_te.te_cfg)){
+ sdla_t1_rx_intr(card);
+ }else{
+ sdla_e1_rx_intr(card);
+ }
+ return;
+}
+
+/*
+ ******************************************************************************
+ * sdla_t1_rx_intr()
+ *
+ * Description: Read tx interrupt.
+ * Arguments: card - pointer to device structure.
+ * Returns: None.
+ ******************************************************************************
+ */
+static void sdla_t1_rx_intr(sdla_t* card)
+{
+ unsigned char intr_src1 = 0x00, intr_src2 = 0x00, intr_src3 = 0x00;
+ unsigned char status = 0x00;
+
+ intr_src1 = READ_REG(REG_INT_SRC_1);
+ intr_src2 = READ_REG(REG_INT_SRC_2);
+ intr_src3 = READ_REG(REG_INT_SRC_3);
+
+ if (!(intr_src1 & BITS_RX_INT_SRC_1 ||
+ intr_src2 & BITS_RX_INT_SRC_2 ||
+ intr_src3 & BITS_RX_INT_SRC_3)){
+ return;
+ }
+
+ /* 3. PDVD */
+ if (intr_src3 & BIT_INT_SRC_3_PDVD){
+ status = READ_REG(REG_PDVD_INT_EN_STATUS);
+ if ((status & BIT_PDVD_INT_EN_STATUS_PDVE) &&
+ (status & BIT_PDVD_INT_EN_STATUS_PDVI)){
+ if (status & BIT_PDVD_INT_EN_STATUS_PDV){
+ log(LOG_INFO, "%s: T1 pulse density violation detected!\n",
+ card->devname);
+ }
+ }
+ if ((status & BIT_PDVD_INT_EN_STATUS_Z16DE) &&
+ (status & BIT_PDVD_INT_EN_STATUS_Z16DI)){
+ log(LOG_INFO, "%s: T1 16 consecutive zeros detected!\n",
+ card->devname);
+ }
+ }
+
+ /* 6. ALMI */
+ if (intr_src3 & BIT_INT_SRC_3_ALMI){
+ status = READ_REG(REG_T1_ALMI_INT_STATUS);
+ if (status & BIT_T1_ALMI_INT_STATUS_YELI){
+ if (status & BIT_T1_ALMI_INT_STATUS_YEL){
+ if (!(card->fe_te.te_alarm & BIT_YEL_ALARM)){
+ log(LOG_INFO, "%s: T1 YELLOW ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_YEL_ALARM;
+ }
+ }else{
+ if (card->fe_te.te_alarm & BIT_YEL_ALARM){
+ log(LOG_INFO, "%s: T1 YELLOW OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_YEL_ALARM;
+ }
+ }
+ }
+ if (status & BIT_T1_ALMI_INT_STATUS_REDI){
+ if (status & BIT_T1_ALMI_INT_STATUS_RED){
+ if (!(card->fe_te.te_alarm & BIT_RED_ALARM)){
+ log(LOG_INFO, "%s: T1 RED ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_RED_ALARM;
+ }
+ }else{
+ if (card->fe_te.te_alarm & BIT_RED_ALARM){
+ log(LOG_INFO, "%s: T1 RED OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_RED_ALARM;
+ }
+ }
+ }
+ if (status & BIT_T1_ALMI_INT_STATUS_AISI){
+ if (status & BIT_T1_ALMI_INT_STATUS_AIS){
+ if (!(card->fe_te.te_alarm & BIT_AIS_ALARM)){
+ log(LOG_INFO, "%s: T1 AIS ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_AIS_ALARM;
+ }
+ }else{
+ if (card->fe_te.te_alarm & BIT_AIS_ALARM){
+ log(LOG_INFO, "%s: T1 AIS OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_AIS_ALARM;
+ }
+ }
+ }
+
+#if 0
+ if (status &
+ (BIT_T1_ALMI_INT_STATUS_YELI |
+ BIT_T1_ALMI_INT_STATUS_REDI |
+ BIT_T1_ALMI_INT_STATUS_AISI)){
+ if (status & (BIT_T1_ALMI_INT_STATUS_YEL |
+ BIT_T1_ALMI_INT_STATUS_RED |
+ BIT_T1_ALMI_INT_STATUS_AIS)){
+
+ /* Update T1/E1 alarm status */
+ if (!(card->fe_te.te_alarm & BIT_YEL_ALARM) &&
+ (status & BIT_T1_ALMI_INT_STATUS_YEL)){
+ log(LOG_INFO, "%s: T1 YELLOW ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_YEL_ALARM;
+ }
+ if (!(card->fe_te.te_alarm & BIT_RED_ALARM) &&
+ (status & BIT_T1_ALMI_INT_STATUS_RED)){
+ log(LOG_INFO, "%s: T1 RED ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_RED_ALARM;
+ }
+ if (!(card->fe_te.te_alarm & BIT_AIS_ALARM) &&
+ (status & BIT_T1_ALMI_INT_STATUS_AIS)){
+ log(LOG_INFO, "%s: T1 AIS ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_AIS_ALARM;
+ }
+ }else{
+ /* Update T1/E1 alarm status */
+ if ((card->fe_te.te_alarm & BIT_YEL_ALARM) &&
+ !(status & BIT_T1_ALMI_INT_STATUS_YEL)){
+ log(LOG_INFO, "%s: T1 YELLOW OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_YEL_ALARM;
+ }
+ if ((card->fe_te.te_alarm & BIT_RED_ALARM) &&
+ !(status & BIT_T1_ALMI_INT_STATUS_RED)){
+ log(LOG_INFO, "%s: T1 RED OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_RED_ALARM;
+ }
+ if ((card->fe_te.te_alarm & BIT_AIS_ALARM) &&
+ !(status & BIT_T1_ALMI_INT_STATUS_AIS)){
+ log(LOG_INFO, "%s: T1 ALMI OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_AIS_ALARM;
+ }
+ }
+ }
+#endif
+ }
+
+ /* 8. RBOC */
+ if (intr_src3 & BIT_INT_SRC_3_RBOC){
+ status = READ_REG(REG_T1_RBOC_CODE_STATUS);
+ if (status & BIT_T1_RBOC_CODE_STATUS_BOCI){
+ struct timeval tv;
+ unsigned long time;
+
+ microtime(&tv);
+ time = tv.tv_sec / 1000;
+ status &= MASK_T1_RBOC_CODE_STATUS;
+ switch (status){
+ case LINELB_ACTIVATE_CODE:
+ case LINELB_DEACTIVATE_CODE:
+ if (bit_test((u_int8_t*)&card->fe_te.te_critical,LINELB_WAITING) &&
+ bit_test((u_int8_t*)&card->fe_te.te_critical,LINELB_CODE_BIT)){
+ bit_clear((u_int8_t*)&card->fe_te.te_critical,LINELB_CODE_BIT);
+ break;
+ }
+
+ log(LOG_DEBUG, "%s: T1 LB %s code received.\n",
+ card->devname,
+ (status == LINELB_ACTIVATE_CODE) ?
+ "activation" :
+ "deactivation");
+ card->fe_te.te_rx_lb_cmd = status;
+ card->fe_te.te_rx_lb_time = time;
+ break;
+
+ case LINELB_DS1LINE_ALL:
+ if (bit_test((u_int8_t*)&card->fe_te.te_critical, LINELB_WAITING) &&
+ bit_test((u_int8_t*)&card->fe_te.te_critical, LINELB_CHANNEL_BIT)){
+ bit_clear((u_int8_t*)&card->fe_te.te_critical,LINELB_CHANNEL_BIT);
+ bit_clear((u_int8_t*)&card->fe_te.te_critical,LINELB_WAITING);
+ break;
+ }
+ if (!card->fe_te.te_rx_lb_cmd)
+ break;
+ if ((time - card->fe_te.te_rx_lb_time) <
+ LINELB_TE1_TIMER){
+ log(LOG_INFO, "%s: T1 LB %s cancel!\n",
+ card->devname,
+ (card->fe_te.te_rx_lb_cmd ==
+ LINELB_ACTIVATE_CODE)?
+ "activatation":
+ "deactivation");
+ }else{
+ unsigned char reg;
+ if (card->fe_te.te_rx_lb_cmd ==
+ LINELB_ACTIVATE_CODE){
+ log(LOG_INFO, "%s: T1 LB activated.\n",
+ card->devname);
+ reg=READ_REG(REG_MASTER_DIAG);
+ reg|=BIT_MASTER_DIAG_LINELB;
+ WRITE_REG(REG_MASTER_DIAG,reg);
+ }else{
+ log(LOG_INFO, "%s: T1 LB deactivated.\n",
+ card->devname);
+ reg=READ_REG(REG_MASTER_DIAG);
+ reg&=~BIT_MASTER_DIAG_LINELB;
+ WRITE_REG(REG_MASTER_DIAG,reg);
+ }
+ }
+ card->fe_te.te_rx_lb_cmd = 0x00;
+ card->fe_te.te_rx_lb_time = 0x00;
+ break;
+
+ case LINELB_DS3LINE:
+ break;
+
+ case LINELB_DS1LINE_1:
+ case LINELB_DS1LINE_2:
+ case LINELB_DS1LINE_3:
+ case LINELB_DS1LINE_4:
+ case LINELB_DS1LINE_5:
+ case LINELB_DS1LINE_6:
+ case LINELB_DS1LINE_7:
+ case LINELB_DS1LINE_8:
+ case LINELB_DS1LINE_9:
+ case LINELB_DS1LINE_10:
+ case LINELB_DS1LINE_11:
+ case LINELB_DS1LINE_12:
+ case LINELB_DS1LINE_13:
+ case LINELB_DS1LINE_14:
+ case LINELB_DS1LINE_15:
+ case LINELB_DS1LINE_16:
+ case LINELB_DS1LINE_17:
+ case LINELB_DS1LINE_18:
+ case LINELB_DS1LINE_19:
+ case LINELB_DS1LINE_20:
+ case LINELB_DS1LINE_21:
+ case LINELB_DS1LINE_22:
+ case LINELB_DS1LINE_23:
+ case LINELB_DS1LINE_24:
+ case LINELB_DS1LINE_25:
+ case LINELB_DS1LINE_26:
+ case LINELB_DS1LINE_27:
+ case LINELB_DS1LINE_28:
+ if (!card->fe_te.te_rx_lb_cmd)
+ break;
+ if ((time - card->fe_te.te_rx_lb_time) <
+ LINELB_TE1_TIMER){
+ log(LOG_DEBUG, "%s: T1 LB %s cancel!\n",
+ card->devname,
+ (card->fe_te.te_rx_lb_cmd ==
+ LINELB_ACTIVATE_CODE) ?
+ "activatation":
+ "deactivation");
+ }else{
+ int channel;
+
+ channel = status & LINELB_DS1LINE_MASK;
+ log(LOG_INFO, "%s: T1 LB %s ts %d\n",
+ card->devname,
+ (card->fe_te.te_rx_lb_cmd ==
+ LINELB_ACTIVATE_CODE) ?
+ "activated" :
+ "deactivated",
+ channel);
+ SetLoopBackChannel(
+ card,
+ channel,
+ card->fe_te.te_rx_lb_cmd);
+ }
+ card->fe_te.te_rx_lb_cmd = 0x00;
+ card->fe_te.te_rx_lb_time = 0x00;
+ break;
+
+ default:
+ log(LOG_DEBUG, "%s: Unknown signal (%02x).\n",
+ card->devname, status);
+ break;
+ }
+ }
+ }
+
+ /* 7. FRMR */
+ if (intr_src1 & BIT_INT_SRC_1_FRMR){
+ status = READ_REG(REG_T1_FRMR_INT_STATUS);
+ if ((READ_REG(REG_T1_FRMR_INT_EN) & BIT_T1_FRMR_INT_EN_INFRE) &&
+ (status & BIT_T1_FRMR_INT_STATUS_INFRI)){
+ if (status & BIT_T1_FRMR_INT_STATUS_INFR){
+ if (!(card->fe_te.te_alarm & BIT_OOF_ALARM)){
+ log(LOG_INFO, "%s: T1 OOF ON!\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_OOF_ALARM;
+ }
+ }else{
+ if (card->fe_te.te_alarm & BIT_OOF_ALARM){
+ log(LOG_INFO, "%s: T1 OOF OFF!\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_OOF_ALARM;
+ }
+ }
+ }
+ }
+
+ /* 1. RLPS */
+ if (intr_src3 & BIT_INT_SRC_3_RLPS){
+ status = READ_REG(REG_RLPS_CFG_STATUS);
+ if ((status & BIT_RLPS_CFG_STATUS_ALOSE) &&
+ (status & BIT_RLPS_CFG_STATUS_ALOSI)){
+ if (status & BIT_RLPS_CFG_STATUS_ALOSV){
+ if (!(card->fe_te.te_alarm & BIT_ALOS_ALARM)){
+ log(LOG_INFO, "%s: T1 ALOS ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_ALOS_ALARM;
+ }
+ }else{
+ if (card->fe_te.te_alarm & BIT_ALOS_ALARM){
+ log(LOG_INFO, "%s: T1 ALOS OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_ALOS_ALARM;
+ }
+ }
+ }
+ }
+
+ /* 2. CDRC */
+ if (intr_src1 & BIT_INT_SRC_1_CDRC){
+ status = READ_REG(REG_CDRC_INT_STATUS);
+ if ((READ_REG(REG_CDRC_INT_EN) & BIT_CDRC_INT_EN_LOSE) &&
+ (status & BIT_CDRC_INT_STATUS_LOSI)){
+ if (status & BIT_CDRC_INT_STATUS_LOSV){
+ if (!(card->fe_te.te_alarm & BIT_LOS_ALARM)){
+ log(LOG_INFO, "%s: T1 LOS ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_LOS_ALARM;
+ }
+ }else{
+ if (card->fe_te.te_alarm & BIT_LOS_ALARM){
+ log(LOG_INFO, "%s: T1 LOS OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_LOS_ALARM;
+ }
+ }
+ }
+ if ((READ_REG(REG_CDRC_INT_EN) & BIT_CDRC_INT_EN_LCVE) &&
+ (status & BIT_CDRC_INT_STATUS_LCVI)){
+ log(LOG_INFO, "%s: T1 line code violation!\n",
+ card->devname);
+ }
+ if ((READ_REG(REG_CDRC_INT_EN) & BIT_CDRC_INT_EN_LCSDE) &&
+ (status & BIT_CDRC_INT_STATUS_LCSDI)){
+ log(LOG_INFO, "%s: T1 line code signature detected!\n",
+ card->devname);
+ }
+ if ((READ_REG(REG_CDRC_INT_EN) & BIT_CDRC_INT_EN_ZNDE) &&
+ (status & BIT_CDRC_INT_STATUS_ZNDI)){
+ log(LOG_INFO, "%s: T1 consecutive zeros detected!\n",
+ card->devname);
+ }
+ status = READ_REG(REG_ALTLOS_STATUS);
+ if ((status & BIT_ALTLOS_STATUS_ALTLOSI) &&
+ (status & BIT_ALTLOS_STATUS_ALTLOSE)){
+ if (status & BIT_ALTLOS_STATUS_ALTLOS){
+ if (!(card->fe_te.te_alarm & BIT_ALTLOS_ALARM)){
+ log(LOG_INFO, "%s: T1 ALTLOS ON\n",
+ card->devname);
+ card->fe_te.te_alarm |=
+ BIT_ALTLOS_ALARM;
+ }
+ }else{
+ if (card->fe_te.te_alarm & BIT_ALTLOS_ALARM){
+ log(LOG_INFO, "%s: T1 ALTLOS OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &=
+ ~BIT_ALTLOS_ALARM;
+ }
+ }
+ }
+ }
+
+ /* 14. PMON */
+ if (intr_src1 & BIT_INT_SRC_1_PMON){
+ status = READ_REG(REG_PMON_INT_EN_STATUS);
+ if (status & BIT_PMON_INT_EN_STATUS_XFER){
+ log(LOG_DEBUG, "%s: T1 Updating PMON counters...\n",
+ card->devname);
+ sdla_te_pmon(card);
+ }
+ }
+
+ /* 9. SIGX */
+ if (intr_src1 & BIT_INT_SRC_1_SIGX){
+ unsigned char SIGX_chg_30_25;
+ unsigned char SIGX_chg_24_17;
+ unsigned char SIGX_chg_16_9;
+ unsigned char SIGX_chg_8_1;
+
+ SIGX_chg_30_25 = READ_REG(REG_SIGX_CFG);
+ SIGX_chg_24_17 = READ_REG(REG_SIGX_TIMESLOT_IND_STATUS);
+ SIGX_chg_16_9 = READ_REG(REG_SIGX_TIMESLOT_IND_ACCESS);
+ SIGX_chg_8_1 = READ_REG(REG_SIGX_TIMESLOT_IND_DATA_BUFFER);
+
+ }
+
+ /* 5. IBCD */
+ card->fe_te.te_alarm &= ~(BIT_LOOPUP_CODE|BIT_LOOPDOWN_CODE);
+ if (intr_src3 & BIT_INT_SRC_3_IBCD){
+ status = READ_REG(REG_IBCD_INT_EN_STATUS);
+ if (status & BIT_IBCD_INT_EN_STATUS_LBAI){
+ card->fe_te.te_alarm |= BIT_LOOPUP_CODE;
+ }
+ if (status & BIT_IBCD_INT_EN_STATUS_LBDI){
+ card->fe_te.te_alarm |= BIT_LOOPDOWN_CODE;
+ }
+ }
+#if 0
+ /* 4. RJAT */
+ if (intr_src1 & BIT_INT_SRC_1_RJAT){
+ }
+ /* 10. RX-ELST */
+ if (intr_src2 & BIT_INT_SRC_2_RX_ELST){
+ }
+ /* 11. RDLC-1 */
+ if (intr_src2 & BIT_INT_SRC_2_RDLC_1){
+ }
+ /* 12. RDLC-2 */
+ if (intr_src2 & BIT_INT_SRC_2_RDLC_2){
+ }
+ /* 13. RDLC-3 */
+ if (intr_src2 & BIT_INT_SRC_2_RDLC_3){
+ }
+#endif
+
+ return;
+}
+
+
+/*
+ ******************************************************************************
+ * sdla_e1_rx_intr()
+ *
+ * Description: Read tx interrupt.
+ * Arguments: card - pointer to device structure.
+ * Returns: None.
+ ******************************************************************************
+ */
+static void sdla_e1_rx_intr(sdla_t* card)
+{
+ unsigned char intr_src1 = 0x00, intr_src2 = 0x00, intr_src3 = 0x00;
+ unsigned char int_status = 0x00, status = 0x00;
+
+ intr_src1 = READ_REG(REG_INT_SRC_1);
+ intr_src2 = READ_REG(REG_INT_SRC_2);
+ intr_src3 = READ_REG(REG_INT_SRC_3);
+ if (!(intr_src1 & BITS_RX_INT_SRC_1 ||
+ intr_src2 & BITS_RX_INT_SRC_2 ||
+ intr_src3 & BITS_RX_INT_SRC_3))
+ return;
+
+ /* 4. FRMR */
+ if (intr_src1 & BIT_INT_SRC_1_FRMR){
+ /* Register 0x94h E1 FRMR */
+ int_status = READ_REG(REG_E1_FRMR_FRM_STAT_INT_IND);
+ /* Register 0x96h E1 FRMR Status */
+ status = READ_REG(REG_E1_FRMR_FR_STATUS);
+ if ((READ_REG(REG_E1_FRMR_FRM_STAT_INT_EN) &
+ BIT_E1_FRMR_FRM_STAT_INT_EN_OOFE) &&
+ (int_status & BIT_E1_FRMR_FRM_STAT_INT_IND_OOFI)){
+ if (status & BIT_E1_FRMR_FR_STATUS_OOFV){
+ if (!(card->fe_te.te_alarm & BIT_OOF_ALARM)){
+ log(LOG_INFO, "%s: E1 OOF ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_OOF_ALARM;
+ }
+ }else{
+ if (card->fe_te.te_alarm & BIT_OOF_ALARM){
+ log(LOG_INFO, "%s: E1 OOF OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_OOF_ALARM;
+ }
+ }
+ }
+
+ if ((READ_REG(REG_E1_FRMR_FRM_STAT_INT_EN) &
+ BIT_E1_FRMR_FRM_STAT_INT_EN_OOSMFE) &&
+ (int_status & BIT_E1_FRMR_FRM_STAT_INT_IND_OOSMFI)){
+ if (status & BIT_E1_FRMR_FR_STATUS_OOSMFV){
+ log(LOG_INFO, "%s: E1 OOSMF ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_OOSMF_ALARM;
+ }else{
+ log(LOG_INFO, "%s: E1 OOSMF OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_OOSMF_ALARM;
+ }
+ }
+
+ if ((READ_REG(REG_E1_FRMR_FRM_STAT_INT_EN) &
+ BIT_E1_FRMR_FRM_STAT_INT_EN_OOCMFE) &&
+ (int_status & BIT_E1_FRMR_FRM_STAT_INT_IND_OOCMFI)){
+ if (status & BIT_E1_FRMR_FR_STATUS_OOCMFV){
+ log(LOG_INFO, "%s: E1 OOCMF ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_OOCMF_ALARM;
+ }else{
+ log(LOG_INFO, "%s: E1 OOCMF OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_OOCMF_ALARM;
+ }
+ }
+
+ /* Register 0x9Fh E1 FRMR */
+ status = READ_REG(REG_E1_FRMR_P_A_INT_STAT);
+ if ((READ_REG(REG_E1_FRMR_P_A_INT_EN) &
+ BIT_E1_FRMR_P_A_INT_EN_OOOFE) &&
+ (status & BIT_E1_FRMR_P_A_INT_STAT_OOOFI)){
+ if (READ_REG(REG_E1_FRMR_FR_STATUS) &
+ BIT_E1_FRMR_FR_STATUS_OOOFV){
+ log(LOG_INFO, "%s: E1 OOOF ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_OOOF_ALARM;
+ }else{
+ log(LOG_INFO, "%s: E1 OOOF OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_OOOF_ALARM;
+ }
+ }
+
+ /* Register 0x95h E1 FRMR */
+ int_status = READ_REG(REG_E1_FRMR_M_A_INT_IND);
+ if (int_status & (BIT_E1_FRMR_M_A_INT_IND_REDI |
+ BIT_E1_FRMR_M_A_INT_IND_AISI)){
+ status = READ_REG(REG_E1_FRMR_MAINT_STATUS);
+ if ((READ_REG(REG_E1_FRMR_M_A_INT_EN) &
+ BIT_E1_FRMR_M_A_INT_EN_REDE) &&
+ (int_status & BIT_E1_FRMR_M_A_INT_IND_REDI)){
+ if (status & BIT_E1_FRMR_MAINT_STATUS_RED){
+ log(LOG_INFO, "%s: E1 RED ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_RED_ALARM;
+ }else{
+ log(LOG_INFO, "%s: E1 RED OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_RED_ALARM;
+ }
+ }
+ if ((READ_REG(REG_E1_FRMR_M_A_INT_EN) &
+ BIT_E1_FRMR_M_A_INT_EN_AISE) &&
+ (int_status & BIT_E1_FRMR_M_A_INT_IND_AISI)){
+ if (status & BIT_E1_FRMR_MAINT_STATUS_AIS){
+ log(LOG_INFO, "%s: E1 AIS ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_AIS_ALARM;
+ }else{
+ log(LOG_INFO, "%s: E1 AIS OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_AIS_ALARM;
+ }
+ }
+ if ((READ_REG(REG_E1_FRMR_M_A_INT_EN) &
+ BIT_E1_FRMR_M_A_INT_EN_RAIE) &&
+ (int_status & BIT_E1_FRMR_M_A_INT_IND_RAII)){
+ if (status & BIT_E1_FRMR_MAINT_STATUS_RAIV){
+ log(LOG_INFO, "%s: E1 RAI ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_RAI_ALARM;
+ }else{
+ log(LOG_INFO, "%s: E1 RAI OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_RAI_ALARM;
+ }
+ }
+ }
+ }
+
+ /* 1. RLPS */
+ if (intr_src3 & BIT_INT_SRC_3_RLPS){
+ status = READ_REG(REG_RLPS_CFG_STATUS);
+ if ((status & BIT_RLPS_CFG_STATUS_ALOSE) &&
+ (status & BIT_RLPS_CFG_STATUS_ALOSI)){
+ if (status & BIT_RLPS_CFG_STATUS_ALOSV){
+ if (!(card->fe_te.te_alarm & BIT_ALOS_ALARM)){
+ log(LOG_INFO, "%s: E1 ALOS ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_ALOS_ALARM;
+ }
+ }else{
+ if (card->fe_te.te_alarm & BIT_ALOS_ALARM){
+ log(LOG_INFO, "%s: E1 ALOS is OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &=
+ ~BIT_ALOS_ALARM;
+ }
+ }
+ }
+ }
+
+ /* 2. CDRC */
+ if (intr_src1 & BIT_INT_SRC_1_CDRC){
+ status = READ_REG(REG_CDRC_INT_STATUS);
+ if ((READ_REG(REG_CDRC_INT_EN) & BIT_CDRC_INT_EN_LOSE) &&
+ (status & BIT_CDRC_INT_STATUS_LOSI)){
+ if (status & BIT_CDRC_INT_STATUS_LOSV){
+ if (!(card->fe_te.te_alarm & BIT_LOS_ALARM)){
+ log(LOG_INFO, "%s: E1 LOS is ON\n",
+ card->devname);
+ card->fe_te.te_alarm |= BIT_LOS_ALARM;
+ }
+ }else{
+ if (card->fe_te.te_alarm & BIT_LOS_ALARM){
+ log(LOG_INFO, "%s: E1 LOS is OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &= ~BIT_LOS_ALARM;
+ }
+ }
+ }
+ if ((READ_REG(REG_CDRC_INT_EN) & BIT_CDRC_INT_EN_LCVE) &&
+ (status & BIT_CDRC_INT_STATUS_LCVI)){
+ log(LOG_INFO, "%s: E1 line code violation!\n",
+ card->devname);
+ }
+ if ((READ_REG(REG_CDRC_INT_EN) & BIT_CDRC_INT_EN_LCSDE) &&
+ (status & BIT_CDRC_INT_STATUS_LCSDI)){
+ log(LOG_INFO, "%s: E1 line code signature detected!\n",
+ card->devname);
+ }
+ if ((READ_REG(REG_CDRC_INT_EN) & BIT_CDRC_INT_EN_ZNDE) &&
+ (status & BIT_CDRC_INT_STATUS_ZNDI)){
+ log(LOG_INFO, "%s: E1 consecutive zeros detected!\n",
+ card->devname);
+ }
+ status = READ_REG(REG_ALTLOS_STATUS);
+ if ((status & BIT_ALTLOS_STATUS_ALTLOSI) &&
+ (status & BIT_ALTLOS_STATUS_ALTLOSE)){
+ if (status & BIT_ALTLOS_STATUS_ALTLOS){
+ if (!(card->fe_te.te_alarm & BIT_ALTLOS_ALARM)){
+ log(LOG_INFO, "%s: E1 ALTLOS is ON\n",
+ card->devname);
+ card->fe_te.te_alarm |=
+ BIT_ALTLOS_ALARM;
+ }
+ }else{
+ if (card->fe_te.te_alarm & BIT_ALTLOS_ALARM){
+ log(LOG_INFO, "%s: E1 ALTLOS is OFF\n",
+ card->devname);
+ card->fe_te.te_alarm &=
+ ~BIT_ALTLOS_ALARM;
+ }
+ }
+ }
+ }
+ /* 11. PMON */
+ if (intr_src1 & BIT_INT_SRC_1_PMON){
+ status = READ_REG(REG_PMON_INT_EN_STATUS);
+ if (status & BIT_PMON_INT_EN_STATUS_XFER){
+ sdla_te_pmon(card);
+ }
+ }
+#if 0
+ /* 3. RJAT */
+ if (intr_src1 & BIT_INT_SRC_1_RJAT){
+ }
+ /* 5. SIGX */
+ if (intr_src1 & BIT_INT_SRC_1_SIGX){
+ }
+ /* 6. RX-ELST */
+ if (intr_src2 & BIT_INT_SRC_2_RX_ELST){
+ }
+ /* 7. PRGD */
+ if (intr_src1 & BIT_INT_SRC_1_PRGD){
+ }
+ /* 8. RDLC-1 */
+ if (intr_src2 & BIT_INT_SRC_2_RDLC_1){
+ }
+ /* 9. RDLC-2 */
+ if (intr_src2 & BIT_INT_SRC_2_RDLC_2){
+ }
+ /* 10. RDLC-3 */
+ if (intr_src2 & BIT_INT_SRC_2_RDLC_3){
+ }
+#endif
+ if (!(READ_REG(REG_RLPS_CFG_STATUS) & BIT_RLPS_CFG_STATUS_ALOSV)){
+ card->fe_te.te_alarm &= ~BIT_ALOS_ALARM;
+ }
+ return;
+}
+
+/*
+ ******************************************************************************
+ * sdla_set_te1_lb_modes()
+ *
+ * Description: Set T1/E1 loopback modes.
+ ******************************************************************************
+ */
+int sdla_set_te1_lb_modes(void* arg, unsigned char type, unsigned char mode)
+{
+ sdla_t* card = (sdla_t*)arg;
+ int err = 1;
+
+ WAN_ASSERT(card->write_front_end_reg == NULL);
+ WAN_ASSERT(card->read_front_end_reg == NULL);
+ switch (type){
+ case WAN_TE1_LINELB_MODE:
+ err = sdla_te_linelb(card, mode);
+ break;
+ case WAN_TE1_PAYLB_MODE:
+ err = sdla_te_paylb(card, mode);
+ break;
+ case WAN_TE1_DDLB_MODE:
+ err = sdla_te_ddlb(card, mode);
+ break;
+ case WAN_TE1_TX_LB_MODE:
+ err = sdla_te_lb(card, mode);
+ break;
+ }
+
+ return err;
+}
+
+/*
+ ******************************************************************************
+ * sdla_te_linelb()
+ *
+ * Description: Activate/Deactivate Line Loopback mode.
+ ******************************************************************************
+ */
+static int sdla_te_linelb(sdla_t* card, unsigned char mode)
+{
+ WAN_ASSERT(card->write_front_end_reg == NULL);
+ WAN_ASSERT(card->read_front_end_reg == NULL);
+ if (mode == WAN_TE1_ACTIVATE_LB){
+ log(LOG_INFO, "%s: %s Line Loopback mode activated.\n",
+ card->devname,
+ (IS_T1(&card->fe_te.te_cfg) ? "T1" : "E1"));
+ WRITE_REG(REG_MASTER_DIAG,
+ READ_REG(REG_MASTER_DIAG) | BIT_MASTER_DIAG_LINELB);
+ }else{
+ log(LOG_INFO, "%s: %s Line Loopback mode deactivated.\n",
+ card->devname,
+ (IS_T1(&card->fe_te.te_cfg) ? "T1" : "E1"));
+ WRITE_REG(REG_MASTER_DIAG,
+ READ_REG(REG_MASTER_DIAG) & ~BIT_MASTER_DIAG_LINELB);
+ }
+ return 0;
+}
+
+/*
+ ******************************************************************************
+ * sdla_te_paylb()
+ *
+ * Description: Activate/Deactivate Payload loopback mode.
+ ******************************************************************************
+ */
+static int sdla_te_paylb(sdla_t* card, unsigned char mode)
+{
+ WAN_ASSERT(card->write_front_end_reg == NULL);
+ WAN_ASSERT(card->read_front_end_reg == NULL);
+ if (mode == WAN_TE1_ACTIVATE_LB){
+ log(LOG_INFO, "%s: %s Payload Loopback mode activated.\n",
+ card->devname,
+ (IS_T1(&card->fe_te.te_cfg) ? "T1" : "E1"));
+ WRITE_REG(REG_MASTER_DIAG,
+ READ_REG(REG_MASTER_DIAG) | BIT_MASTER_DIAG_PAYLB);
+ }else{
+ log(LOG_INFO, "%s: %s Payload Loopback mode deactivated.\n",
+ card->devname,
+ (IS_T1(&card->fe_te.te_cfg) ? "T1" : "E1"));
+ WRITE_REG(REG_MASTER_DIAG,
+ READ_REG(REG_MASTER_DIAG) & ~BIT_MASTER_DIAG_PAYLB);
+ }
+ return 0;
+}
+
+/*
+ ******************************************************************************
+ * sdla_te_ddlb()
+ *
+ * Description: Activate/Deactivate Diagnostic Digital loopback mode.
+ ******************************************************************************
+ */
+static int sdla_te_ddlb(sdla_t* card, unsigned char mode)
+{
+ WAN_ASSERT(card->write_front_end_reg == NULL);
+ WAN_ASSERT(card->read_front_end_reg == NULL);
+ if (mode == WAN_TE1_ACTIVATE_LB){
+ log(LOG_INFO, "%s: %s Diagnostic Dig. LB mode activated.\n",
+ card->devname,
+ (IS_T1(&card->fe_te.te_cfg) ? "T1" : "E1"));
+ WRITE_REG(REG_MASTER_DIAG,
+ READ_REG(REG_MASTER_DIAG) | BIT_MASTER_DIAG_DDLB);
+ }else{
+ log(LOG_INFO, "%s: %s Diagnostic Dig. LB mode deactivated.\n",
+ card->devname,
+ (IS_T1(&card->fe_te.te_cfg) ? "T1" : "E1"));
+ WRITE_REG(REG_MASTER_DIAG,
+ READ_REG(REG_MASTER_DIAG) & ~BIT_MASTER_DIAG_DDLB);
+ }
+ return 0;
+}
+
+/*
+ ******************************************************************************
+ * sdla_te_timer()
+ ******************************************************************************
+ */
+void sdla_te_timer(void* card_id)
+{
+ sdla_t *card = (sdla_t*)card_id;
+
+ if (bit_test((u_int8_t*)&card->fe_te.te_critical,TE_TIMER_KILL)){
+ bit_clear((u_int8_t*)&card->fe_te.te_critical,TE_TIMER_RUNNING);
+ return;
+ }
+ /*WAN_ASSERT1(card->te_enable_timer == NULL); */
+ /* Enable hardware interrupt for TE1 */
+ if (card->te_enable_timer){
+ card->te_enable_timer(card);
+ }else{
+ sdla_te_polling(card);
+ }
+
+ return;
+}
+
+/*
+ ******************************************************************************
+ * sdla_te_enable_timer()
+ *
+ * Description: Enable software timer interrupt in delay ms.
+ ******************************************************************************
+ */
+static void sdla_te_enable_timer(sdla_t* card, unsigned long delay)
+{
+
+ WAN_ASSERT1(card == NULL);
+ if (bit_test((u_int8_t*)&card->fe_te.te_critical, TE_TIMER_KILL)){
+ bit_clear((u_int8_t*)&card->fe_te.te_critical,
+ TE_TIMER_RUNNING);
+ return;
+ }
+ bit_set((u_int8_t*)&card->fe_te.te_critical, TE_TIMER_RUNNING);
+
+ timeout_add(&card->fe_te.te_timer, delay * hz / 1000);
+ return;
+}
+
+/*
+ ******************************************************************************
+ * sdla_te_polling()
+ *
+ * Description: Process T1/E1 polling function.
+ ******************************************************************************
+ */
+void sdla_te_polling(void* card_id)
+{
+ sdla_t* card = (sdla_t*)card_id;
+
+ WAN_ASSERT1(card->write_front_end_reg == NULL);
+ WAN_ASSERT1(card->read_front_end_reg == NULL);
+ bit_clear((u_int8_t*)&card->fe_te.te_critical, TE_TIMER_RUNNING);
+ switch (card->fe_te.te_timer_cmd){
+ case TE_LINELB_TIMER:
+ if (IS_T1(&card->fe_te.te_cfg)){
+ /* Sending T1 activation/deactivation LB signal */
+ if (card->fe_te.te_tx_lb_cnt > 10){
+ WRITE_REG(REG_T1_XBOC_CODE,
+ (card->fe_te.te_tx_lb_cmd ==
+ WAN_TE1_ACTIVATE_LB) ?
+ LINELB_ACTIVATE_CODE :
+ LINELB_DEACTIVATE_CODE);
+ }else{
+ WRITE_REG(REG_T1_XBOC_CODE,
+ LINELB_DS1LINE_ALL);
+ }
+ if (--card->fe_te.te_tx_lb_cnt){
+ sdla_te_enable_timer(card, LINELB_TE1_TIMER);
+ }else{
+ log(LOG_DEBUG, "%s: TX T1 LB %s signal.\n",
+ card->devname,
+ (card->fe_te.te_tx_lb_cmd ==
+ WAN_TE1_ACTIVATE_LB) ?
+ "activation" :
+ "deactivation");
+ card->fe_te.te_tx_lb_cmd = 0x00;
+ bit_clear((u_int8_t*)&card->fe_te.te_critical,
+ TE_TIMER_RUNNING);
+ }
+ }
+ break;
+
+ case TE_SET_INTR:
+ sdla_te_set_intr(card);
+ break;
+
+ case TE_LINKDOWN_TIMER:
+ if ((READ_REG(REG_RLPS_ALOS_DET_PER) &&
+ (READ_REG(REG_RLPS_CFG_STATUS) &
+ BIT_RLPS_CFG_STATUS_ALOSV)) ||
+ (IS_E1(&card->fe_te.te_cfg) &&
+ (READ_REG(REG_E1_FRMR_FR_STATUS) &
+ BIT_E1_FRMR_FR_STATUS_OOFV)) ||
+ (IS_T1(&card->fe_te.te_cfg) &&
+ (READ_REG(REG_T1_FRMR_INT_STATUS) &
+ ~BIT_T1_FRMR_INT_STATUS_INFR))){
+ sdla_te_enable_timer(card, POLLING_TE1_TIMER);
+ }else{
+ /* All other interrupt reports status changed
+ * through interrupts, we don't need to read
+ * these values here */
+ sdla_te_set_status(card, card->fe_te.te_alarm);
+ if (card->front_end_status == FE_CONNECTED){
+ card->fe_te.te_timer_cmd = TE_LINKUP_TIMER;
+ sdla_te_enable_timer(card, POLLING_TE1_TIMER);
+ }
+ }
+ break;
+
+ case TE_LINKUP_TIMER:
+ /* ALEX:
+ * Do not update protocol front end state from
+ * TE_LINKDOWN_TIMER because it cause to stay
+ * more longer in interrupt handler (critical for XILINX
+ * code) */
+ if (card->te_link_state){
+ card->te_link_state(card);
+ }
+ break;
+ }
+ return;
+}
+
+/*
+ ******************************************************************************
+ * sdla_te_lb()
+ *
+ * Description: Transmit loopback signal to remote side.
+ ******************************************************************************
+ */
+static int sdla_te_lb(sdla_t* card, unsigned char mode)
+{
+ WAN_ASSERT(card->write_front_end_reg == NULL);
+ WAN_ASSERT(card->read_front_end_reg == NULL);
+
+ if (!IS_T1(&card->fe_te.te_cfg)){
+ return 1;
+ }
+ if (card->front_end_status != FE_CONNECTED){
+ return 1;
+ }
+ if (bit_test((u_int8_t*)&card->fe_te.te_critical,TE_TIMER_RUNNING))
+ return 1;
+ if (bit_test((u_int8_t*)&card->fe_te.te_critical,LINELB_WAITING)){
+ log(LOG_DEBUG, "%s: Waiting for loopback signal!\n",
+ card->devname);
+ }
+ log(LOG_DEBUG, "%s: Sending %s loopback %s signal...\n",
+ card->devname,
+ (IS_T1(&card->fe_te.te_cfg) ? "T1" : "E1"),
+ (mode == WAN_TE1_ACTIVATE_LB) ?
+ "activation" : "deactivation");
+ card->fe_te.te_tx_lb_cmd = mode;
+ card->fe_te.te_tx_lb_cnt = LINELB_CODE_CNT + LINELB_CHANNEL_CNT;
+ card->fe_te.te_timer_cmd = TE_LINELB_TIMER;
+ bit_set((u_int8_t*)&card->fe_te.te_critical, LINELB_WAITING);
+ bit_set((u_int8_t*)&card->fe_te.te_critical, LINELB_CODE_BIT);
+ bit_set((u_int8_t*)&card->fe_te.te_critical, LINELB_CHANNEL_BIT);
+ sdla_te_enable_timer(card, LINELB_TE1_TIMER);
+
+ return 0;
+}
+
+
+
+/*
+ ******************************************************************************
+ * sdla_te_udp()
+ ******************************************************************************
+ */
+int sdla_te_udp(void* card_id, void* cmd, unsigned char* data)
+{
+ sdla_t *card = (sdla_t*)card_id;
+ wan_cmd_t *udp_cmd = (wan_cmd_t*)cmd;
+ int err = 0;
+
+ switch (udp_cmd->wan_cmd_command){
+ case WAN_GET_MEDIA_TYPE:
+ data[0] =
+ IS_T1(&card->fe_te.te_cfg) ? WANOPT_MEDIA_T1 :
+ IS_E1(&card->fe_te.te_cfg) ? WANOPT_MEDIA_E1 :
+ WANOPT_MEDIA_NONE;
+ udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
+ udp_cmd->wan_cmd_data_len = sizeof(unsigned char);
+ break;
+
+ case WAN_FE_SET_LB_MODE:
+ /* Activate/Deactivate Line Loopback modes */
+ err = sdla_set_te1_lb_modes(card, data[0], data[1]);
+ udp_cmd->wan_cmd_return_code =
+ (!err) ? WAN_CMD_OK : WAN_UDP_FAILED_CMD;
+ udp_cmd->wan_cmd_data_len = 0x00;
+ break;
+
+ case WAN_FE_GET_STAT:
+ /* TE1_56K Read T1/E1/56K alarms */
+ *(unsigned long *)&data[0] = sdla_te_alarm(card, 0);
+ /* TE1 Update T1/E1 perfomance counters */
+ sdla_te_pmon(card);
+ memcpy(&data[sizeof(unsigned long)],
+ &card->fe_te.te_pmon,
+ sizeof(pmc_pmon_t));
+ udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
+ udp_cmd->wan_cmd_data_len =
+ sizeof(unsigned long) + sizeof(pmc_pmon_t);
+
+ break;
+
+ case WAN_FE_FLUSH_PMON:
+ /* TE1 Flush T1/E1 pmon counters */
+ sdla_flush_te1_pmon(card);
+ udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
+ break;
+
+ case WAN_FE_GET_CFG:
+ /* Read T1/E1 configuration */
+ memcpy(&data[0],
+ &card->fe_te.te_cfg,
+ sizeof(sdla_te_cfg_t));
+ udp_cmd->wan_cmd_return_code = WAN_CMD_OK;
+ udp_cmd->wan_cmd_data_len = sizeof(sdla_te_cfg_t);
+ break;
+
+ default:
+ udp_cmd->wan_cmd_return_code = WAN_UDP_INVALID_CMD;
+ udp_cmd->wan_cmd_data_len = 0;
+ break;
+ }
+ return 0;
+}
+
+
+void aft_green_led_ctrl(void *card_id, int mode)
+{
+ sdla_t* card = (sdla_t*)card_id;
+ unsigned char led;
+
+ if (!card->read_front_end_reg ||
+ !card->write_front_end_reg){
+ return;
+ }
+
+ led= READ_REG(REG_GLOBAL_CFG);
+
+ if (mode == AFT_LED_ON){
+ led&=~(BIT_GLOBAL_PIO);
+ }else if (mode == AFT_LED_OFF){
+ led|=BIT_GLOBAL_PIO;
+ }else{
+ if (led&BIT_GLOBAL_PIO){
+ led&=~(BIT_GLOBAL_PIO);
+ }else{
+ led|=BIT_GLOBAL_PIO;
+ }
+ }
+
+ WRITE_REG(REG_GLOBAL_CFG,led);
+}
+/************************** End of files *************************************/
diff --git a/sys/dev/pci/if_san_te1.h b/sys/dev/pci/if_san_te1.h
new file mode 100644
index 00000000000..714ca3f7f6d
--- /dev/null
+++ b/sys/dev/pci/if_san_te1.h
@@ -0,0 +1,987 @@
+/*-
+ * Copyright (c) 2001-2004 Sangoma Technologies (SAN)
+ * All rights reserved. www.sangoma.com
+ *
+ * This code is written by Alex Feldman <al.feldman@sangoma.com> for SAN.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sangoma Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SANGOMA TECHNOLOGIES AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __IF_SANTE1_H
+# define __IF_SANTE1_H
+
+#ifdef SDLA_TE1
+# define EXTERN
+#else
+# define EXTERN extern
+#endif
+
+/***********************************************************************
+* INCLUDE *
+***********************************************************************/
+# include <dev/pci/if_san_front_end.h>
+
+/***********************************************************************
+* DEFINES AND MACROS *
+***********************************************************************/
+
+#define REG_GLOBAL_CFG 0x00
+#define BIT_GLOBAL_PIO_OE 0x80
+#define BIT_GLOBAL_PIO 0x40
+#define BIT_GLOBAL_TRKEN 0x04
+#define BIT_GLOBAL_E1 0x01
+
+#define REG_RLPS_ALOS_DET_PER_0 0x01
+
+#define REG_RECEIVE_OPT 0x02
+#define BIT_RECEIVE_OPT_UNF 0x40
+
+#define REG_TX_TIMING_OPT 0x06
+#define BIT_TX_PLLREF1 0x08
+#define BIT_TX_PLLREF0 0x04
+#define BIT_TX_TXELSTBYP 0x01
+
+#define REG_MASTER_DIAG 0x0A
+#define BIT_MASTER_DIAG_PAYLB 0x20
+#define BIT_MASTER_DIAG_LINELB 0x10
+#define BIT_MASTER_DIAG_DDLB 0x04
+
+#define REG_RESET 0x0E
+#define BIT_RESET 0x01
+
+#define REG_PRGD_CTRL 0x0F
+#define BIT_PRGD_CTRL_HDLC3 0x80
+#define BIT_PRGD_CTRL_HDLC2 0x40
+#define BIT_PRGD_CTRL_HDLC1 0x20
+#define BIT_PRGD_CTRL_Nx56k_GEN 0x10
+#define BIT_PRGD_CTRL_Nx56k_DET 0x08
+#define BIT_PRGD_CTRL_RXPATGEN 0x04
+#define BIT_PRGD_CTRL_UNF_GEN 0x02
+#define BIT_PRGD_CTRL_UNF_DET 0x01
+
+#define REG_CDRC_CFG 0x10
+#define BIT_CDRC_CFG_AMI 0x80
+#define BIT_CDRC_CFG_LOS1 0x40
+#define BIT_CDRC_CFG_LOS0 0x20
+
+#define REG_CDRC_INT_STATUS 0x12
+#define BIT_CDRC_INT_STATUS_LCVI 0x80
+#define BIT_CDRC_INT_STATUS_LOSI 0x40
+#define BIT_CDRC_INT_STATUS_LCSDI 0x20
+#define BIT_CDRC_INT_STATUS_ZNDI 0x10
+#define BIT_CDRC_INT_STATUS_LOSV 0x01
+
+#define REG_ALTLOS_STATUS 0x13
+#define BIT_ALTLOS_STATUS_ALTLOSE 0x80
+#define BIT_ALTLOS_STATUS_ALTLOSI 0x40
+#define BIT_ALTLOS_STATUS_ALTLOS 0x01
+
+#define REG_RJAT_CFG 0x17
+#define BIT_RJAT_CENT 0x10
+
+#define REG_TJAT_CFG 0x1B
+#define BIT_TJAT_CENT 0x10
+
+#define REG_RX_ELST_CFG 0x1C
+#define MASK_RX_ELST_CFG 0x03
+#define BIT_RX_ELST_IR 0x02
+#define BIT_RX_ELST_OR 0x01
+
+#define REG_TX_ELST_CFG 0x20
+#define MASK_TX_ELST_CFG 0x03
+#define BIT_TX_ELST_IR 0x02
+#define BIT_TX_ELST_OR 0x01
+
+#define REG_BRIF_CFG 0x30
+#define BIT_BRIF_NXDS0_1 0x80
+#define BIT_BRIF_NXDS0_0 0x40
+#define BIT_BRIF_CMODE 0x20
+#define BIT_BRIF_RATE0 0x01
+
+#define REG_BRIF_FR_PULSE_CFG 0x31
+#define BIT_BRIF_FPMODE 0x20
+#define BIT_BRIF_ROHM 0x08
+
+#define REG_BRIF_DATA_CFG 0x32
+#define BIT_BRIF_DATA_TRI_0 0x01
+
+#define REG_BTIF_CFG 0x40
+#define BIT_BTIF_NXDS0_1 0x80
+#define BIT_BTIF_NXDS0_0 0x40
+#define BIT_BTIF_CMODE 0x20
+#define BIT_BTIF_DE 0x10
+#define BIT_BTIF_FE 0x08
+#define BIT_BTIF_RATE0 0x01
+
+#define REG_BTIF_FR_PULSE_CFG 0x41
+#define BIT_BTIF_FPMODE 0x01
+
+#define REG_BTIF_CFG_STATUS 0x42
+#define BIT_BTIF_CFG_STATUS_TPTYP 0x80
+#define BIT_BTIF_CFG_STATUS_TPTYE 0x40
+#define BIT_BTIF_CFG_STATUS_TDI 0x20
+#define BIT_BTIF_CFG_STATUS_TSIGI 0x10
+#define BIT_BTIF_CFG_STATUS_PTY_EXTD 0x08
+
+#define REG_BTIF_BIT_OFF 0x44
+#define BIT_BTIF_BIT_OFF_BOFF_EN 0x08
+#define BIT_BTIF_BIT_OFF_BOFF_2 0x04
+#define BIT_BTIF_BIT_OFF_BOFF_1 0x02
+#define BIT_BTIF_BIT_OFF_BOFF_0 0x01
+
+#define REG_T1_FRMR_CFG 0x48
+#define BIT_T1_FRMR_ESF 0x20
+#define BIT_T1_FRMR_ESFFA 0x10
+#define BIT_T1_FRMR_FMS1 0x08
+#define BIT_T1_FRMR_FMS0 0x04
+
+#define REG_SIGX_CFG 0x50
+#define BIT_SIGX_ESF 0x04
+#define BIT_SIGX_IND 0x02
+#define BIT_SIGX_PCCE 0x01
+#define BIT_SIGX_SIGE 0x20
+#define BIT_SIGX_COSS 0x40
+#define MASK_SIGX_COSS_30_25 0x3F
+
+#define REG_SIGX_TIMESLOT_IND_STATUS 0x51
+#define BIT_SIGX_BUSY 0x80
+#define REG_SIGX_TIMESLOT_IND_ACCESS 0x52
+#define BIT_SIGX_TS_IND_ACCESS_READ 0x80
+#define REG_SIGX_TIMESLOT_IND_DATA_BUFFER 0x53
+#define REG_SIGX_SIGDATA 0x20
+#define BIT_SIGX_SIGDATA_A 0x08
+#define BIT_SIGX_SIGDATA_B 0x04
+#define BIT_SIGX_SIGDATA_C 0x02
+#define BIT_SIGX_SIGDATA_D 0x01
+
+#define REG_SIGX_CHANCFG 0x40
+#define BIT_SIGX_CHANCFG_RINV1 0x08
+#define BIT_SIGX_CHANCFG_RINV0 0x04
+#define BIT_SIGX_CHANCFG_RFIX 0x04
+#define BIT_SIGX_CHANCFG_RPOL 0x02
+#define BIT_SIGX_CHANCFG_RDEBE 0x01
+
+#define REG_T1_XBAS_CFG 0x54
+#define BIT_T1_XBAS_ZCS0 0x01
+#define BIT_T1_XBAS_ZCS1 0x02
+#define BIT_T1_XBAS_B8ZS 0x20
+#define BIT_T1_XBAS_ESF 0x10
+
+#define REG_T1_XBAS_ALARM_TX 0x55
+#define BIT_T1_XBAS_ALARM_TX_XYEL 0x02
+#define BIT_T1_XBAS_ALARM_TX_XAIS 0x01
+
+/* PMON Framing Bit Error Count */
+#define REG_PMON_BIT_ERROR 0x59
+#define BITS_PMON_BIT_ERROR 0x7F
+/* PMON OOF/COFA/Far End Block Error Count LSB */
+#define REG_PMON_OOF_FEB_LSB_ERROR 0x5A
+/* PMON OOF/COFA/Far End Block Error Count MSB */
+#define REG_PMON_OOF_FEB_MSB_ERROR 0x5B
+#define BITS_PMON_OOF_FEB_MSB_ERROR 0x03
+/* PMON Bit Error/CRC Error Count LSB */
+#define REG_PMON_BIT_CRC_LSB_ERROR 0x5C
+/* PMON Bit Error/CRC Error Count MSB */
+#define REG_PMON_BIT_CRC_MSB_ERROR 0x5D
+#define BITS_PMON_BIT_CRC_MSB_ERROR 0x03
+/* PMON LCV Count LSB */
+#define REG_PMON_LCV_LSB_COUNT 0x5E
+/* PMON LCV Count MSB */
+#define REG_PMON_LCV_MSB_COUNT 0x5F
+#define BITS_PMON_LCV_MSB_COUNT 0x1F
+
+#define REG_T1_ALMI_CFG 0x60
+#define BIT_T1_ALMI_CFG_ESF 0x10
+#define BIT_T1_ALMI_CFG_FMS1 0x08
+#define BIT_T1_ALMI_CFG_FMS0 0x04
+
+#define REG_T1_ALMI_DET_STATUS 0x63
+#define BIT_T1_ALMI_DET_STATUS_REDD 0x04
+#define BIT_T1_ALMI_DET_STATUS_YELD 0x02
+#define BIT_T1_ALMI_DET_STATUS_AISD 0x01
+
+/* T1 XBOC Code */
+#define REG_T1_XBOC_CODE 0x67
+#define MASK_T1_XBOC_CODE 0x3F
+
+/* T1 RBOC Enable */
+#define REG_T1_RBOC_ENABLE 0x6A
+#define BIT_T1_RBOC_ENABLE_IDLE 0x04
+#define BIT_T1_RBOC_ENABLE_AVC 0x02
+#define BIT_T1_RBOC_ENABLE_BOCE 0x01
+
+/* T1 RBOC Code Status */
+#define REG_T1_RBOC_CODE_STATUS 0x6B
+#define BIT_T1_RBOC_CODE_STATUS_IDLEI 0x80
+#define BIT_T1_RBOC_CODE_STATUS_BOCI 0x40
+#define MASK_T1_RBOC_CODE_STATUS 0x3F
+
+/* TPSC Indirect Register Access */
+#define REG_TPSC_CFG 0x6C
+#define MASK_TPSC_CFG 0x03
+#define BIT_TPSC_IND 0x02
+#define BIT_TPSC_PCCE 0x01
+#define REG_TPSC_MICRO_ACCESS_STATUS 0x6D
+#define BIT_TPSC_BUSY 0x80
+#define REG_TPSC_CHANNEL_INDIRECT_ADDRESS_CONTROL 0x6E
+#define REG_TPSC_CHANNEL_INDIRECT_DATA_BUFFER 0x6F
+#define REG_TPSC_DATA_CTRL_BYTE 0x20
+#define MASK_TPSC_DATA_CTRL_BYTE 0xFC
+#define BIT_TPSC_DATA_CTRL_BYTE_INVERT 0x80
+#define BIT_TPSC_DATA_CTRL_BYTE_IDLE_DS0 0x40
+#define BIT_TPSC_DATA_CTRL_BYTE_SIGNINV 0x10
+#define BIT_TPSC_DATA_CTRL_BYTE_LOOP 0x04
+#define BIT_TPSC_DATA_CTRL_BYTE_ZCS0 0x02
+#define BIT_TPSC_DATA_CTRL_BYTE_ZCS1 0x01
+#define REG_TPSC_IDLE_CODE_BYTE 0x40
+#define REG_TPSC_SIGNALING_BYTE 0x60
+#define REG_TPSC_E1_CTRL_BYTE 0x60
+#define BIT_TPSC_E1_CTRL_BYTE_SUBS 0x80
+#define BIT_TPSC_E1_CTRL_BYTE_DS0 0x40
+#define BIT_TPSC_E1_CTRL_BYTE_DS1 0x20
+#define BIT_TPSC_E1_CTRL_BYTE_A 0x08
+#define BIT_TPSC_E1_CTRL_BYTE_B 0x04
+#define BIT_TPSC_E1_CTRL_BYTE_C 0x02
+#define BIT_TPSC_E1_CTRL_BYTE_D 0x01
+#define BIT_TPSC_SIGNALING_BYTE_SIGC_0 0x80
+#define BIT_TPSC_SIGNALING_BYTE_SIGC_1 0x40
+#define BIT_TPSC_SIGNALING_BYTE_DS1 0x20
+#define BIT_TPSC_SIGNALING_BYTE_A 0x08
+#define BIT_TPSC_SIGNALING_BYTE_B 0x04
+#define BIT_TPSC_SIGNALING_BYTE_C 0x02
+#define BIT_TPSC_SIGNALING_BYTE_D 0x01
+
+/* RPSC Indirect Register Access */
+#define REG_RPSC_CFG 0x70
+#define MASK_RPSC_CFG 0x03
+#define BIT_RPSC_IND 0x02
+#define BIT_RPSC_PCCE 0x01
+#define REG_RPSC_MICRO_ACCESS_STATUS 0x71
+#define BIT_RPSC_BUSY 0x80
+#define REG_RPSC_CHANNEL_INDIRECT_ADDRESS_CONTROL 0x72
+#define REG_RPSC_CHANNEL_INDIRECT_DATA_BUFFER 0x73
+#define REG_RPSC_DATA_CTRL_BYTE 0x20
+#define MASK_RPSC_DATA_CTRL_BYTE 0xFC
+#define BIT_RPSC_DATA_CTRL_BYTE_DTRKC 0x40
+#define BIT_RPSC_DATA_CTRL_BYTE_SIGNINV 0x04
+#define REG_RPSC_DATA_COND_BYTE 0x40
+#define REG_RPSC_SIGNALING_BYTE 0x60
+#define BIT_RPSC_SIGNALING_BYTE_A 0x08
+#define BIT_RPSC_SIGNALING_BYTE_B 0x04
+#define BIT_RPSC_SIGNALING_BYTE_C 0x02
+#define BIT_RPSC_SIGNALING_BYTE_D 0x01
+
+#define REG_E1_TRAN_CFG 0x80
+#define BIT_E1_TRAN_AMI 0x80
+#define BIT_E1_TRAN_GENCRC 0x10
+#define BIT_E1_TRAN_FDIS 0x08
+#define BIT_E1_TRAN_FEBEDIS 0x04
+#define BIT_E1_TRAN_INDIS 0x02
+#define BIT_E1_TRAN_XDIS 0x01
+
+#define REG_E1_FRMR_CFG 0x90
+#define BIT_E1_FRMR_CRCEN 0x80
+#define BIT_E1_FRMR_CASDIS 0x40
+#define BIT_E1_FRMR_REFCRCEN 0x02
+
+/* E1 FRMR Maintenance Mode Options */
+#define REG_E1_FRMR_MAINT_OPT 0x91
+#define BIT_E1_FRMR_MAINT_OPT_AISC 0x02
+
+/* E1 FRMR framing status */
+#define REG_E1_FRMR_FR_STATUS 0x96
+#define BIT_E1_FRMR_FR_STATUS_C2NCIWV 0x80
+#define BIT_E1_FRMR_FR_STATUS_OOFV 0x40
+#define BIT_E1_FRMR_FR_STATUS_OOSMFV 0x20
+#define BIT_E1_FRMR_FR_STATUS_OOCMFV 0x10
+#define BIT_E1_FRMR_FR_STATUS_OOOFV 0x08
+#define BIT_E1_FRMR_FR_STATUS_RAICCRCV 0x04
+#define BIT_E1_FRMR_FR_STATUS_CFEBEV 0x02
+#define BIT_E1_FRMR_FR_STATUS_V52LINKV 0x01
+
+/* E1 FRMR Maintenance/Alram Status */
+#define REG_E1_FRMR_MAINT_STATUS 0x97
+#define BIT_E1_FRMR_MAINT_STATUS_RAIV 0x80
+#define BIT_E1_FRMR_MAINT_STATUS_RED 0x08
+#define BIT_E1_FRMR_MAINT_STATUS_AIS 0x04
+
+ /* TDPR Configuration */
+#define REG_TDPR_CFG 0xA8
+#define BIT_TDPR_CFG_EN 0x01
+
+/* TDPR Transmit Data */
+#define REG_TDPR_TX_DATA 0xAD
+
+/* RDLC Configuration */
+#define REG_RDLC_CFG 0xC0
+#define BIT_RDLC_CFG_EN 0x01
+
+/* RDLC Interrupt Control */
+#define REG_RDLC_INT_CTRL 0xC1
+#define BIT_RDLC_INT_CTRL_INTE 0x80
+
+/* RDLC Status */
+#define REG_RDLC_STATUS 0xC2
+#define BIT_RDLC_STATUS_PKIN 0x10
+#define BIT_RDLC_STATUS_INTR 0x01
+
+/* RDLC Data */
+#define REG_RDLC_DATA 0xC3
+
+#define REG_CSU_CFG 0xD6
+#define MASK_CSU_CFG 0xC7
+#define BIT_CSU_MODE2 0x04
+#define BIT_CSU_MODE1 0x02
+#define BIT_CSU_MODE0 0x01
+
+/* RLPS Equalization Indirect Data (MSB) */
+#define REG_RLPS_IND_DATA_1 0xD8
+/* RLPS Equalization Indirect Data */
+#define REG_RLPS_IND_DATA_2 0xD9
+/* RLPS Equalization Indirect Data */
+#define REG_RLPS_IND_DATA_3 0xDA
+/* RLPS Equalization Indirect Data (LSB) */
+#define REG_RLPS_IND_DATA_4 0xDB
+
+#define REG_EQ_VREF 0xDC
+
+#define REG_RLPS_FUSE_CTRL_STAT 0xDD
+
+#define REG_XLPG_LINE_CFG 0xF0
+#define REG_PRGD_INT_STATUS_EN 0xE1
+#define BIT_PRGD_INT_STATUS_EN_SYNCE 0x80
+#define BIT_PRGD_INT_STATUS_EN_BEE 0x40
+#define BIT_PRGD_INT_STATUS_EN_XFERE 0x20
+#define BIT_PRGD_INT_STATUS_EN_SYNCV 0x10
+#define BIT_PRGD_INT_STATUS_EN_SYNCI 0x08
+#define BIT_PRGD_INT_STATUS_EN_BEI 0x04
+#define BIT_PRGD_INT_STATUS_EN_XFERI 0x02
+#define BIT_PRGD_INT_STATUS_EN_OVR 0x01
+
+#define REG_XLPG_WAVEFORM_ADDR 0xF2
+
+#define REG_XLPG_WAVEFORM_DATA 0xF3
+
+#define REG_XLPG_TPC 0xF4
+#define BIT_XLPG_TPC_0 0x01
+
+#define REG_XLPG_TNC 0xF5
+#define BIT_XLPG_TNC_0 0x01
+
+#define REG_RLPS_CFG_STATUS 0xF8
+#define BIT_RLPS_CFG_STATUS_ALOSI 0x80
+#define BIT_RLPS_CFG_STATUS_ALOSV 0x40
+#define BIT_RLPS_CFG_STATUS_ALOSE 0x20
+#define BIT_RLPS_CFG_STATUS_LONGE 0x01
+
+#define REG_RLPS_ALOS_DET_CLR_THR 0xF9
+#define BIT_RLPS_ALOS_CLR_THR_2 0x40
+#define BIT_RLPS_ALOS_CLR_THR_1 0x20
+#define BIT_RLPS_ALOS_CLR_THR_0 0x10
+#define BIT_RLPS_ALOS_DET_THR_2 0x04
+#define BIT_RLPS_ALOS_DET_THR_1 0x02
+#define BIT_RLPS_ALOS_DET_THR_0 0x01
+
+#define REG_RLPS_ALOS_DET_PER 0xFA
+
+#define REG_RLPS_ALOS_CLR_PER 0xFB
+#define BIT_RLPS_ALOS_CLR_PER_0 0x01
+
+/* RLPS Equalization Indirect Address */
+#define REG_RLPS_EQ_ADDR 0xFC
+
+/* RLPS Equalization Read/Write Select */
+#define REG_RLPS_EQ_RWB 0xFD
+#define BIT_RLPS_EQ_RWB 0x80
+
+#define REG_RLPS_EQ_STATUS 0xFE
+
+#define REG_RLPS_EQ_CFG 0xFF
+#define MASK_RLPS_EQ_CFG 0xC7
+#define BIT_RLPS_EQ_RESERVED 0x08
+#define BIT_RLPS_EQ_FREQ_1 0x02
+#define BIT_RLPS_EQ_FREQ_0 0x01
+
+/********************************************/
+/************ Interrupt Register ************/
+/********************************************/
+#define REG_INT_SRC_1 0x07
+#define BITS_TX_INT_SRC_1 0x0C
+#define BITS_RX_INT_SRC_1 0xF3
+#define BIT_INT_SRC_1_PMON 0x80
+#define BIT_INT_SRC_1_PRGD 0x40
+#define BIT_INT_SRC_1_FRMR 0x20
+#define BIT_INT_SRC_1_SIGX 0x10
+#define BIT_INT_SRC_1_APRM 0x08
+#define BIT_INT_SRC_1_TJAT 0x04
+#define BIT_INT_SRC_1_RJAT 0x02
+#define BIT_INT_SRC_1_CDRC 0x01
+
+#define REG_INT_SRC_2 0x08
+#define BITS_TX_INT_SRC_2 0x0F
+#define BITS_RX_INT_SRC_2 0xF0
+#define BIT_INT_SRC_2_RX_ELST 0x80
+#define BIT_INT_SRC_2_RDLC_3 0x40
+#define BIT_INT_SRC_2_RDLC_2 0x20
+#define BIT_INT_SRC_2_RDLC_1 0x10
+#define BIT_INT_SRC_2_TX_ELST 0x08
+#define BIT_INT_SRC_2_TDPR_3 0x04
+#define BIT_INT_SRC_2_TDPR_2 0x02
+#define BIT_INT_SRC_2_TDPR_1 0x01
+
+#define REG_INT_SRC_3 0x09
+#define BITS_TX_INT_SRC_3 0x15
+#define BITS_RX_INT_SRC_3 0xEA
+#define BIT_INT_SRC_3_IBCD 0x80
+#define BIT_INT_SRC_3_PDVD 0x40
+#define BIT_INT_SRC_3_RBOC 0x20
+#define BIT_INT_SRC_3_XPDE 0x10
+#define BIT_INT_SRC_3_ALMI 0x08
+#define BIT_INT_SRC_3_TRAN 0x04
+#define BIT_INT_SRC_3_RLPS 0x02
+#define BIT_INT_SRC_3_BTIF 0x01
+
+#define REG_CDRC_INT_EN 0x11
+#define BIT_CDRC_INT_EN_LCVE 0x80
+#define BIT_CDRC_INT_EN_LOSE 0x40
+#define BIT_CDRC_INT_EN_LCSDE 0x20
+#define BIT_CDRC_INT_EN_ZNDE 0x10
+
+#define REG_CDRC_INT_STATUS 0x12
+#define BIT_CDRC_INT_STATUS_LCVI 0x80
+#define BIT_CDRC_INT_STATUS_LOSI 0x40
+#define BIT_CDRC_INT_STATUS_LCSDI 0x20
+#define BIT_CDRC_INT_STATUS_ZNDI 0x10
+#define BIT_CDRC_INT_STATUS_LOSV 0x01
+
+#define REG_RJAT_INT_STATUS 0x14
+#define BIT_RJAT_INT_STATUS_OVRI 0x02
+#define BIT_RJAT_INT_STATUS_UNDI 0x01
+
+#define REG_TJAT_INT_STATUS 0x18
+#define BIT_TJAT_INT_STATUS_OVRI 0x02
+#define BIT_TJAT_INT_STATUS_UNDI 0x01
+
+#define REG_RX_ELST_INT_EN_STATUS 0x1D
+#define BIT_RX_ELST_INT_EN_STATUS_SLIPE 0x04
+#define BIT_RX_ELST_INT_EN_STATUS_SLIPD 0x02
+#define BIT_RX_ELST_INT_EN_STATUS_SLIPI 0x01
+
+#define REG_TX_ELST_INT_EN_STATUS 0x21
+#define BIT_TX_ELST_INT_EN_STATUS_SLIPE 0x04
+#define BIT_TX_ELST_INT_EN_STATUS_SLIPD 0x02
+#define BIT_TX_ELST_INT_EN_STATUS_SLIPI 0x01
+
+#define REG_T1_FRMR_INT_EN 0x49
+#define BIT_T1_FRMR_INT_EN_COFAE 0x20
+#define BIT_T1_FRMR_INT_EN_FERE 0x10
+#define BIT_T1_FRMR_INT_EN_BEEE 0x08
+#define BIT_T1_FRMR_INT_EN_SFEE 0x04
+#define BIT_T1_FRMR_INT_EN_MFPE 0x02
+#define BIT_T1_FRMR_INT_EN_INFRE 0x01
+
+#define REG_T1_FRMR_INT_STATUS 0x4A
+#define BIT_T1_FRMR_INT_STATUS_COFAI 0x80
+#define BIT_T1_FRMR_INT_STATUS_FERI 0x40
+#define BIT_T1_FRMR_INT_STATUS_BEEI 0x20
+#define BIT_T1_FRMR_INT_STATUS_SFEI 0x10
+#define BIT_T1_FRMR_INT_STATUS_MFPI 0x08
+#define BIT_T1_FRMR_INT_STATUS_INFRI 0x04
+#define BIT_T1_FRMR_INT_STATUS_MFP 0x02
+#define BIT_T1_FRMR_INT_STATUS_INFR 0x01
+
+#define REG_IBCD_CFG 0x4C
+#define BIT_IBCD_CFG_DSEL1 0x08
+#define BIT_IBCD_CFG_DSEL0 0x04
+#define BIT_IBCD_CFG_ASEL1 0x02
+#define BIT_IBCD_CFG_ASEL0 0x01
+
+#define REG_IBCD_INT_EN_STATUS 0x4D
+#define BIT_IBCD_INT_EN_STATUS_LBACP 0x80
+#define BIT_IBCD_INT_EN_STATUS_LBDCP 0x40
+#define BIT_IBCD_INT_EN_STATUS_LBAE 0x20
+#define BIT_IBCD_INT_EN_STATUS_LBDE 0x10
+#define BIT_IBCD_INT_EN_STATUS_LBAI 0x08
+#define BIT_IBCD_INT_EN_STATUS_LBDI 0x04
+#define BIT_IBCD_INT_EN_STATUS_LBA 0x02
+#define BIT_IBCD_INT_EN_STATUS_LBD 0x01
+
+#define REG_IBCD_ACTIVATE_CODE 0x4E
+#define BIT_IBCD_ACTIVATE_CODE_ACT7 0x80
+#define BIT_IBCD_ACTIVATE_CODE_ACT6 0x40
+#define BIT_IBCD_ACTIVATE_CODE_ACT5 0x20
+#define BIT_IBCD_ACTIVATE_CODE_ACT4 0x10
+#define BIT_IBCD_ACTIVATE_CODE_ACT3 0x08
+#define BIT_IBCD_ACTIVATE_CODE_ACT2 0x04
+#define BIT_IBCD_ACTIVATE_CODE_ACT1 0x02
+#define BIT_IBCD_ACTIVATE_CODE_ACT0 0x01
+
+#define REG_IBCD_DEACTIVATE_CODE 0x4F
+#define BIT_IBCD_DEACTIVATE_CODE_DACT7 0x80
+#define BIT_IBCD_DEACTIVATE_CODE_DACT6 0x40
+#define BIT_IBCD_DEACTIVATE_CODE_DACT5 0x20
+#define BIT_IBCD_DEACTIVATE_CODE_DACT4 0x10
+#define BIT_IBCD_DEACTIVATE_CODE_DACT3 0x08
+#define BIT_IBCD_DEACTIVATE_CODE_DACT2 0x04
+#define BIT_IBCD_DEACTIVATE_CODE_DACT1 0x02
+#define BIT_IBCD_DEACTIVATE_CODE_DACT0 0x01
+
+#define REG_PMON_INT_EN_STATUS 0x58
+#define BIT_PMON_INT_EN_STATUS_INTE 0x04
+#define BIT_PMON_INT_EN_STATUS_XFER 0x02
+#define BIT_PMON_INT_EN_STATUS_OVR 0x01
+
+#define REG_T1_ALMI_INT_EN 0x61
+#define BIT_T1_ALMI_INT_EN_FASTD 0x10
+#define BIT_T1_ALMI_INT_EN_ACCEL 0x08
+#define BIT_T1_ALMI_INT_EN_YELE 0x04
+#define BIT_T1_ALMI_INT_EN_REDE 0x02
+#define BIT_T1_ALMI_INT_EN_AISE 0x01
+
+#define REG_T1_ALMI_INT_STATUS 0x62
+#define BIT_T1_ALMI_INT_STATUS_YELI 0x20
+#define BIT_T1_ALMI_INT_STATUS_REDI 0x10
+#define BIT_T1_ALMI_INT_STATUS_AISI 0x08
+#define BIT_T1_ALMI_INT_STATUS_YEL 0x04
+#define BIT_T1_ALMI_INT_STATUS_RED 0x02
+#define BIT_T1_ALMI_INT_STATUS_AIS 0x01
+
+#define REG_PDVD_INT_EN_STATUS 0x65
+#define BIT_PDVD_INT_EN_STATUS_PDV 0x10
+#define BIT_PDVD_INT_EN_STATUS_Z16DI 0x08
+#define BIT_PDVD_INT_EN_STATUS_PDVI 0x04
+#define BIT_PDVD_INT_EN_STATUS_Z16DE 0x02
+#define BIT_PDVD_INT_EN_STATUS_PDVE 0x01
+
+#define REG_XPDE_INT_EN_STATUS 0x69
+#define BIT_XPDE_INT_EN_STATUS_STUFE 0x80
+#define BIT_XPDE_INT_EN_STATUS_STUFF 0x40
+#define BIT_XPDE_INT_EN_STATUS_STUFI 0x20
+#define BIT_XPDE_INT_EN_STATUS_PDV 0x10
+#define BIT_XPDE_INT_EN_STATUS_Z16DI 0x08
+#define BIT_XPDE_INT_EN_STATUS_PDVI 0x04
+#define BIT_XPDE_INT_EN_STATUS_Z16DE 0x02
+#define BIT_XPDE_INT_EN_STATUS_PDVE 0x01
+
+#define REG_T1_APRM_INT_STATUS 0x7A
+#define BIT_T1_APRM_INT_STATUS_INTR 0x01
+
+#define REG_E1_TRAN_INT_EN 0x84
+#define BIT_E1_TRAN_INT_EN_SIGMFE 0x10
+#define BIT_E1_TRAN_INT_EN_NFASE 0x08
+#define BIT_E1_TRAN_INT_EN_MFE 0x04
+#define BIT_E1_TRAN_INT_EN_SMFE 0x02
+#define BIT_E1_TRAN_INT_EN_FRME 0x01
+
+#define REG_E1_TRAN_INT_STATUS 0x85
+#define BIT_E1_TRAN_INT_STATUS_SIGMFI 0x10
+#define BIT_E1_TRAN_INT_STATUS_NFASI 0x08
+#define BIT_E1_TRAN_INT_STATUS_MFI 0x04
+#define BIT_E1_TRAN_INT_STATUS_SMFI 0x02
+#define BIT_E1_TRAN_INT_STATUS_FRMI 0x01
+
+#define REG_E1_FRMR_FRM_STAT_INT_EN 0x92
+#define BIT_E1_FRMR_FRM_STAT_INT_EN_C2NCIWE 0x80
+#define BIT_E1_FRMR_FRM_STAT_INT_EN_OOFE 0x40
+#define BIT_E1_FRMR_FRM_STAT_INT_EN_OOSMFE 0x20
+#define BIT_E1_FRMR_FRM_STAT_INT_EN_OOCMFE 0x10
+#define BIT_E1_FRMR_FRM_STAT_INT_EN_COFAE 0x08
+#define BIT_E1_FRMR_FRM_STAT_INT_EN_FERE 0x04
+#define BIT_E1_FRMR_FRM_STAT_INT_EN_SMFERE 0x02
+#define BIT_E1_FRMR_FRM_STAT_INT_EN_CMFERE 0x01
+
+#define REG_E1_FRMR_M_A_INT_EN 0x93
+#define BIT_E1_FRMR_M_A_INT_EN_RAIE 0x80
+#define BIT_E1_FRMR_M_A_INT_EN_RMAIE 0x40
+#define BIT_E1_FRMR_M_A_INT_EN_AISDE 0x20
+#define BIT_E1_FRMR_M_A_INT_EN_REDE 0x08
+#define BIT_E1_FRMR_M_A_INT_EN_AISE 0x04
+#define BIT_E1_FRMR_M_A_INT_EN_FEBEE 0x02
+#define BIT_E1_FRMR_M_A_INT_EN_CRCEE 0x01
+
+/* E1 FRMR Framing status Interrupt Indication */
+#define REG_E1_FRMR_FRM_STAT_INT_IND 0x94
+#define BIT_E1_FRMR_FRM_STAT_INT_IND_C2NCIWI 0x80
+#define BIT_E1_FRMR_FRM_STAT_INT_IND_OOFI 0x40
+#define BIT_E1_FRMR_FRM_STAT_INT_IND_OOSMFI 0x20
+#define BIT_E1_FRMR_FRM_STAT_INT_IND_OOCMFI 0x10
+#define BIT_E1_FRMR_FRM_STAT_INT_IND_COFAI 0x08
+#define BIT_E1_FRMR_FRM_STAT_INT_IND_FERI 0x04
+#define BIT_E1_FRMR_FRM_STAT_INT_IND_SMFERI 0x02
+#define BIT_E1_FRMR_FRM_STAT_INT_IND_CMFERI 0x01
+
+#define REG_E1_FRMR_M_A_INT_IND 0x95
+#define BIT_E1_FRMR_M_A_INT_IND_RAII 0x80
+#define BIT_E1_FRMR_M_A_INT_IND_FMAII 0x40
+#define BIT_E1_FRMR_M_A_INT_IND_AISDI 0x20
+#define BIT_E1_FRMR_M_A_INT_IND_REDI 0x08
+#define BIT_E1_FRMR_M_A_INT_IND_AISI 0x04
+#define BIT_E1_FRMR_M_A_INT_IND_FEBEI 0x02
+#define BIT_E1_FRMR_M_A_INT_IND_CRCEI 0x01
+
+#define REG_E1_FRMR_P_A_INT_EN 0x9E
+#define BIT_E1_FRMR_P_A_INT_EN_OOOFE 0x80
+#define BIT_E1_FRMR_P_A_INT_EN_RAICCRCE 0x40
+#define BIT_E1_FRMR_P_A_INT_EN_CFEBEE 0x20
+#define BIT_E1_FRMR_P_A_INT_EN_V52LINKE 0x10
+#define BIT_E1_FRMR_P_A_INT_EN_IFPE 0x08
+#define BIT_E1_FRMR_P_A_INT_EN_ICSMFPE 0x04
+#define BIT_E1_FRMR_P_A_INT_EN_ICMFPE 0x02
+#define BIT_E1_FRMR_P_A_INT_EN_ISMFPE 0x01
+
+#define REG_E1_FRMR_P_A_INT_STAT 0x9F
+#define BIT_E1_FRMR_P_A_INT_STAT_OOOFI 0x80
+#define BIT_E1_FRMR_P_A_INT_STAT_RAICCRCI 0x40
+#define BIT_E1_FRMR_P_A_INT_STAT_CFEBEI 0x20
+#define BIT_E1_FRMR_P_A_INT_STAT_V52LINKI 0x10
+#define BIT_E1_FRMR_P_A_INT_STAT_IFPI 0x08
+#define BIT_E1_FRMR_P_A_INT_STAT_ICSMFPI 0x04
+#define BIT_E1_FRMR_P_A_INT_STAT_ICMFPI 0x02
+#define BIT_E1_FRMR_P_A_INT_STAT_ISMFPI 0x01
+
+/*
+*************************************************************************
+* DEFINES AND MACROS *
+*************************************************************************
+*/
+
+/*The line code */
+#define WANOPT_LC_AMI 0x01
+#define WANOPT_LC_B8ZS 0x02
+#define WANOPT_LC_HDB3 0x03
+
+/* Framing mode (T1/E1)/Unframed */
+#define WANOPT_FR_ESF 0x01
+#define WANOPT_FR_D4 0x02
+#define WANOPT_FR_ESF_JAPAN 0x03
+#define WANOPT_FR_CRC4 0x04
+#define WANOPT_FR_NCRC4 0x05
+#define WANOPT_FR_UNFRAMED 0x06
+
+/* For T1 only */
+#define WANOPT_T1_LBO_0_DB 0x01
+#define WANOPT_T1_LBO_75_DB 0x02
+#define WANOPT_T1_LBO_15_DB 0x03
+#define WANOPT_T1_LBO_225_DB 0x04
+#define WANOPT_T1_0_110 0x05
+#define WANOPT_T1_110_220 0x06
+#define WANOPT_T1_220_330 0x07
+#define WANOPT_T1_330_440 0x08
+#define WANOPT_T1_440_550 0x09
+#define WANOPT_T1_550_660 0x0A
+
+/* For E1 only */
+#define WANOPT_E1_120 0x0B
+#define WANOPT_E1_75 0x0C
+
+/* Clocking Master/Normal */
+#define WANOPT_NORMAL_CLK 0x01
+#define WANOPT_MASTER_CLK 0x02
+
+#define NUM_OF_T1_CHANNELS 24
+#define NUM_OF_E1_TIMESLOTS 31
+#define NUM_OF_E1_CHANNELS 32
+#define ENABLE_ALL_CHANNELS 0xFFFFFFFF
+
+#define E1_FRAMING_TIMESLOT 0
+#define E1_SIGNALING_TIMESLOT 16
+
+/* Alram bit mask */
+#define BIT_ALOS_ALARM 0x0001
+#define BIT_LOS_ALARM 0x0002
+#define BIT_ALTLOS_ALARM 0x0004
+#define BIT_OOF_ALARM 0x0008
+#define BIT_RED_ALARM 0x0010
+#define BIT_AIS_ALARM 0x0020
+#define BIT_OOSMF_ALARM 0x0040
+#define BIT_OOCMF_ALARM 0x0080
+#define BIT_OOOF_ALARM 0x0100
+#define BIT_RAI_ALARM 0x0200
+#define BIT_YEL_ALARM 0x0400
+#define BIT_LOOPUP_CODE 0x2000
+#define BIT_LOOPDOWN_CODE 0x4000
+#define BIT_TE1_ALARM 0x8000 /* for Windows only */
+
+/* Performamce monitor counter defines */
+#define frm_bit_error pmon1 /* E1/T1 */
+#define oof_errors pmon2 /* T1 only */
+#define far_end_blk_errors pmon2 /* E1 only */
+#define bit_errors pmon3 /* T1 only */
+#define crc_errors pmon3 /* E1 only */
+#define lcv pmon4 /* E1/T1 */
+
+/* Line loopback modes */
+#define WAN_TE1_LINELB_MODE 0x01
+#define WAN_TE1_PAYLB_MODE 0x02
+#define WAN_TE1_DDLB_MODE 0x03
+#define WAN_TE1_TX_LB_MODE 0x04
+
+/* Line loopback activate/deactive modes */
+#define WAN_TE1_ACTIVATE_LB 0x01
+#define WAN_TE1_DEACTIVATE_LB 0x02
+
+/* Loopback commands (T1.107-1995 p.44) */
+#define LINELB_TE1_TIMER 40 /* 40ms */
+#define LINELB_CODE_CNT 10 /* no. of repetitions for lb_code */
+#define LINELB_CHANNEL_CNT 10 /* no. of repetitions for channel */
+#define LINELB_ACTIVATE_CODE 0x07
+#define LINELB_DEACTIVATE_CODE 0x1C
+#define LINELB_DS3LINE 0x1B
+#define LINELB_DS1LINE_1 0x21
+#define LINELB_DS1LINE_2 0x22
+#define LINELB_DS1LINE_3 0x23
+#define LINELB_DS1LINE_4 0x24
+#define LINELB_DS1LINE_5 0x25
+#define LINELB_DS1LINE_6 0x26
+#define LINELB_DS1LINE_7 0x27
+#define LINELB_DS1LINE_8 0x28
+#define LINELB_DS1LINE_9 0x29
+#define LINELB_DS1LINE_10 0x2A
+#define LINELB_DS1LINE_11 0x2B
+#define LINELB_DS1LINE_12 0x2C
+#define LINELB_DS1LINE_13 0x2D
+#define LINELB_DS1LINE_14 0x2E
+#define LINELB_DS1LINE_15 0x2F
+#define LINELB_DS1LINE_16 0x30
+#define LINELB_DS1LINE_17 0x31
+#define LINELB_DS1LINE_18 0x32
+#define LINELB_DS1LINE_19 0x33
+#define LINELB_DS1LINE_20 0x34
+#define LINELB_DS1LINE_21 0x35
+#define LINELB_DS1LINE_22 0x36
+#define LINELB_DS1LINE_23 0x37
+#define LINELB_DS1LINE_24 0x38
+#define LINELB_DS1LINE_25 0x39
+#define LINELB_DS1LINE_26 0x3A
+#define LINELB_DS1LINE_27 0x3B
+#define LINELB_DS1LINE_28 0x3C
+#define LINELB_DS1LINE_ALL 0x13
+#define LINELB_DS1LINE_MASK 0x1F
+
+/* Interrupt polling delay */
+#define POLLING_TE1_TIMER 1000 /* 1 sec */
+
+/* TE1 critical flag */
+#define TE_TIMER_RUNNING 0x01
+#define TE_TIMER_KILL 0x02
+#define LINELB_WAITING 0x03
+#define LINELB_CODE_BIT 0x04
+#define LINELB_CHANNEL_BIT 0x05
+#define TE_CONFIGURED 0x06
+
+#if 0
+#define TE_TIMER_RUNNING 0x01
+#define TE_TIMER_KILL 0x02
+#define LINELB_WAITING 0x04
+#define LINELB_CODE_BIT 0x08
+#define LINELB_CHANNEL_BIT 0x10
+#endif
+
+/* TE1 timer flags */
+#define TE_LINELB_TIMER 0x01
+#define TE_LINKDOWN_TIMER 0x02
+#define TE_SET_INTR 0x03
+#define TE_ABCD_UPDATE 0x04
+#define TE_LINKUP_TIMER 0x05
+
+/* TE1 T1/E1 interrupt setting delay */
+#define INTR_TE1_TIMER 150 /* 50 ms */
+
+#define IS_T1(te_cfg) ((te_cfg)->media == WANOPT_MEDIA_T1)
+#define IS_E1(te_cfg) ((te_cfg)->media == WANOPT_MEDIA_E1)
+
+#define IS_TE1(te_cfg) (IS_T1(te_cfg) || IS_E1(te_cfg))
+
+#define IS_TE1_UNFRAMED(card) ((card)->te_cfg.frame == WANOPT_FR_UNFRAMED)
+
+#define GET_TE_CHANNEL_RANGE(card) \
+ (IS_T1(&card->te_cfg) ? NUM_OF_T1_CHANNELS : \
+ IS_E1(&card->te_cfg) ? NUM_OF_E1_CHANNELS :0)
+
+#define ALOS_ALARM(val) (val & BIT_ALOS_ALARM) ? "ON" : "OFF"
+#define LOS_ALARM(val) (val & BIT_LOS_ALARM) ? "ON" : "OFF"
+#define ALTLOS_ALARM(val) (val & BIT_ALTLOS_ALARM) ? "ON" : "OFF"
+#define OOF_ALARM(val) (val & BIT_OOF_ALARM) ? "ON" : "OFF"
+#define RED_ALARM(val) (val & BIT_RED_ALARM) ? "ON" : "OFF"
+#define AIS_ALARM(val) (val & BIT_AIS_ALARM) ? "ON" : "OFF"
+#define OOSMF_ALARM(val) (val & BIT_OOSMF_ALARM) ? "ON" : "OFF"
+#define OOCMF_ALARM(val) (val & BIT_OOCMF_ALARM) ? "ON" : "OFF"
+#define OOOF_ALARM(val) (val & BIT_OOOF_ALARM) ? "ON" : "OFF"
+#define RAI_ALARM(val) (val & BIT_RAI_ALARM) ? "ON" : "OFF"
+#define YEL_ALARM(val) (val & BIT_YEL_ALARM) ? "ON" : "OFF"
+
+#define MEDIA_DECODE(val) (val == WANOPT_MEDIA_T1) ? "T1" : \
+ (val == WANOPT_MEDIA_E1) ? "E1" : "Unknown"
+
+#define LCODE_DECODE(val) (val == WANOPT_LC_AMI) ? "AMI" : \
+ (val == WANOPT_LC_B8ZS) ? "B8ZS" : \
+ (val == WANOPT_LC_HDB3) ? "HDB3" : "Unknown"
+
+#define FRAME_DECODE(val) (val == WANOPT_FR_ESF) ? "ESF" : \
+ (val == WANOPT_FR_D4) ? "D4" : \
+ (val == WANOPT_FR_CRC4) ? "CRC4" : \
+ (val == WANOPT_FR_NCRC4) ? "non-CRC4" : \
+ (val == WANOPT_FR_UNFRAMED) ? "Unframed" : "Unknown"
+
+#define TECLK_DECODE(val) (val == WANOPT_NORMAL_CLK) ? "Normal" : \
+ (val == WANOPT_MASTER_CLK) ? "Master" : "Unknown"
+
+#define LBO_DECODE(val) (val == WANOPT_T1_LBO_0_DB) ? "0db" : \
+ (val == WANOPT_T1_LBO_75_DB) ? "7.5db" : \
+ (val == WANOPT_T1_LBO_15_DB) ? "15dB" : \
+ (val == WANOPT_T1_LBO_225_DB) ? "22.5dB" : \
+ (val == WANOPT_T1_0_110) ? "0-110ft" : \
+ (val == WANOPT_T1_110_220) ? "110-220ft" : \
+ (val == WANOPT_T1_220_330) ? "220-330ft" : \
+ (val == WANOPT_T1_330_440) ? "330-440ft" : \
+ (val == WANOPT_T1_440_550) ? "440-550ft" : \
+ (val == WANOPT_T1_550_660) ? "550-660ft" : "Unknown"
+
+
+/*
+ ******************************************************************************
+ STRUCTURES AND TYPEDEFS
+ ******************************************************************************
+*/
+
+
+/*----------------------------------------------------------------------------
+ * T1/E1 configuration structures.
+ */
+typedef struct sdla_te_cfg {
+ unsigned char media;
+ unsigned char lcode;
+ unsigned char frame;
+ unsigned char lbo;
+ unsigned char te_clock;
+ unsigned long active_ch;
+ unsigned char high_impedance_mode;
+} sdla_te_cfg_t;
+
+/* Performamce monitor counters */
+typedef struct pmc_pmon {
+ unsigned long pmon1;
+ unsigned long pmon2;
+ unsigned long pmon3;
+ unsigned long pmon4;
+} pmc_pmon_t;
+
+#ifdef _KERNEL
+
+/* -----------------------------------------------------------------------------
+ * Constants for the SET_T1_E1_SIGNALING_CFG/READ_T1_E1_SIGNALING_CFG commands
+ * ---------------------------------------------------------------------------*/
+
+/* the structure for setting the signaling permission */
+#pragma pack(1)
+typedef struct {
+ unsigned char time_slot[32];
+} te_signaling_perm_t;
+#pragma pack()
+
+/* settings for the signaling permission structure */
+#define TE_SIG_DISABLED 0x00 /* signaling is disabled */
+#define TE_RX_SIG_ENABLED 0x01 /* receive signaling is enabled */
+#define TE_TX_SIG_ENABLED 0x02 /* transmit signaling is enabled */
+#define TE_SET_TX_SIG_BITS 0x80 /* a flag indicating that outgoing
+ signaling bits should be set */
+
+/* the structure used for the
+ * SET_T1_E1_SIGNALING_CFG/READ_T1_E1_SIGNALING_CFG command
+ */
+#pragma pack(1)
+typedef struct {
+ /* signaling permission structure */
+ te_signaling_perm_t sig_perm;
+ /* loop signaling processing counter */
+ unsigned char sig_processing_counter;
+ /* pointer to the signaling permission structure */
+ unsigned long ptr_te_sig_perm_struct;
+ /* pointer to the receive signaling structure */
+ unsigned long ptr_te_Rx_sig_struct;
+ /* pointer to the transmit signaling structure */
+ unsigned long ptr_te_Tx_sig_struct;
+} te_signaling_cfg_t;
+#pragma pack()
+
+/* the structure used for reading and setting the signaling bits */
+#pragma pack(1)
+typedef struct {
+ unsigned char time_slot[32];
+} te_signaling_status_t;
+#pragma pack()
+
+typedef struct {
+ unsigned char SIGX_chg_30_25;
+ unsigned char SIGX_chg_24_17;
+ unsigned char SIGX_chg_16_9;
+ unsigned char SIGX_chg_8_1;
+
+ unsigned long ptr_te_sig_perm_off;
+ unsigned long ptr_te_Rx_sig_off;
+ unsigned long ptr_te_Tx_sig_off;
+
+ sdla_te_cfg_t te_cfg; /* TE1 hw configuration */
+ unsigned long te_alarm; /* TE1 alarm */
+ pmc_pmon_t te_pmon; /* TE PMON counters */
+ unsigned char te_rx_lb_cmd; /* Received LB cmd */
+ unsigned long te_rx_lb_time; /* Time when LB cmd received */
+
+ unsigned char te_tx_lb_cmd; /* Received LB cmd */
+ unsigned long te_tx_lb_cnt; /* Time when LB cmd received */
+ unsigned char te_critical; /* T1/E1 critical flag */
+ struct timeout te_timer; /* Timer */
+ unsigned char te_timer_cmd;
+} sdla_te_softc_t;
+
+
+
+/*
+ ******************************************************************************
+ FUNCTION PROTOTYPES
+ ******************************************************************************
+*/
+EXTERN int sdla_te_defcfg(void*);
+EXTERN int sdla_te_setcfg(void*,struct ifmedia*);
+EXTERN void sdla_te_settimeslot(void*,unsigned long);
+EXTERN unsigned long sdla_te_gettimeslot(void*);
+EXTERN short sdla_te_config(void*);
+EXTERN void sdla_te_unconfig(void*);
+EXTERN unsigned long sdla_te_alarm(void*, int);
+EXTERN void sdla_te_alarm_print(void*);
+EXTERN void sdla_te_pmon(void*);
+EXTERN void sdla_flush_te1_pmon(void*);
+EXTERN void sdla_te_intr(void*);
+EXTERN int sdla_set_te1_lb_modes(void*, unsigned char, unsigned char);
+EXTERN void sdla_te_polling(void* card_id);
+EXTERN void sdla_te_timer(void*);
+EXTERN int sdla_te_udp(void*, void*, unsigned char *);
+EXTERN void aft_green_led_ctrl(void*, int);
+#endif /* _KERNEL */
+
+#undef EXTERN
+
+#endif /* __IF_SANTE1_H */
diff --git a/sys/dev/pci/if_san_xilinx.c b/sys/dev/pci/if_san_xilinx.c
new file mode 100644
index 00000000000..05c036ec7fb
--- /dev/null
+++ b/sys/dev/pci/if_san_xilinx.c
@@ -0,0 +1,3535 @@
+/*-
+ * Copyright (c) 2001-2004 Sangoma Technologies (SAN)
+ * All rights reserved. www.sangoma.com
+ *
+ * This code is written by Nenad Corbic <ncorbic@sangoma.com> and
+ * Alex Feldman <al.feldman@sangoma.com> for SAN.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sangoma Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SANGOMA TECHNOLOGIES AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+# include </usr/include/bitstring.h>
+# include <sys/types.h>
+# include <sys/param.h>
+# include <sys/systm.h>
+# include <sys/syslog.h>
+# include <sys/ioccom.h>
+# include <sys/malloc.h>
+# include <sys/errno.h>
+# include <sys/mbuf.h>
+# include <sys/socket.h>
+# include <sys/kernel.h>
+# include <sys/time.h>
+# include <sys/timeout.h>
+
+# include <net/bpf.h>
+# include <net/if.h>
+# include <net/if_media.h>
+# include <net/netisr.h>
+# include <net/if_sppp.h>
+# include <netinet/in_systm.h>
+# include <netinet/in.h>
+# include <netinet/in_var.h>
+# include <netinet/udp.h>
+# include <netinet/ip.h>
+
+# include <dev/pci/if_san_common.h>
+# include <dev/pci/if_san_obsd.h>
+# include <dev/pci/if_san_xilinx.h>
+
+/****** Defines & Macros ****************************************************/
+
+/* Private critical flags */
+enum {
+ POLL_CRIT = PRIV_CRIT,
+ TX_BUSY,
+ RX_BUSY,
+ TASK_POLL,
+ CARD_DOWN
+};
+
+enum {
+ LINK_DOWN,
+ DEVICE_DOWN
+};
+
+#define MAX_IP_ERRORS 10
+
+#define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" )
+#define MAX_TX_BUF 10
+#define MAX_RX_BUF 10
+
+#undef DEB_XILINX
+
+#if 1
+# define TRUE_FIFO_SIZE 1
+#else
+# undef TRUE_FIFO_SIZE
+# define HARD_FIFO_CODE 0x01
+#endif
+
+static int aft_rx_copyback=1000;
+
+/******Data Structures*****************************************************/
+
+/* This structure is placed in the private data area of the device structure.
+ * The card structure used to occupy the private area but now the following
+ * structure will incorporate the card structure along with Protocol specific data
+ */
+typedef struct
+{
+ wanpipe_common_t common;
+
+ struct ifqueue wp_tx_free_list;
+ struct ifqueue wp_tx_pending_list;
+ struct ifqueue wp_tx_complete_list;
+ struct ifqueue wp_rx_free_list;
+ struct ifqueue wp_rx_complete_list;
+
+ struct mbuf *tx_dma_mbuf;
+ u_int8_t tx_dma_cnt;
+
+ struct mbuf *rx_dma_mbuf;
+
+ unsigned long time_slot_map;
+ unsigned char num_of_time_slots;
+ long logic_ch_num;
+
+ unsigned char dma_status;
+ unsigned char ignore_modem;
+ struct ifqueue udp_queue;
+
+ unsigned long router_start_time;
+
+ unsigned long tick_counter; /* For 5s timeout counter */
+ unsigned long router_up_time;
+
+ unsigned char mc; /* Mulitcast support on/off */
+ unsigned char udp_pkt_src; /* udp packet processing */
+ unsigned short timer_int_enabled;
+
+ unsigned char interface_down;
+
+ u_int8_t gateway;
+ u_int8_t true_if_encoding;
+
+ char if_name[IFNAMSIZ+1];
+
+ u_int8_t idle_flag;
+ u_int16_t max_idle_size;
+ u_int8_t idle_start;
+
+ u_int8_t pkt_error;
+ u_int8_t rx_fifo_err_cnt;
+
+ int first_time_slot;
+
+ struct mbuf *tx_idle_mbuf;
+ unsigned long tx_dma_addr;
+ unsigned int tx_dma_len;
+ unsigned char rx_dma;
+ unsigned char pci_retry;
+
+ unsigned char fifo_size_code;
+ unsigned char fifo_base_addr;
+ unsigned char fifo_size;
+
+ int dma_mtu;
+
+ void *prot_ch;
+ wan_trace_t trace_info;
+
+}xilinx_softc_t;
+#define WAN_IFP_TO_SOFTC(ifp) (xilinx_softc_t*)((ifp)->if_softc)
+
+/* Route Status options */
+#define NO_ROUTE 0x00
+#define ADD_ROUTE 0x01
+#define ROUTE_ADDED 0x02
+#define REMOVE_ROUTE 0x03
+
+#define WP_WAIT 0
+#define WP_NO_WAIT 1
+
+/* variable for keeping track of enabling/disabling FT1 monitor status */
+/* static int rCount; */
+
+extern void disable_irq(unsigned int);
+extern void enable_irq(unsigned int);
+
+/**SECTOIN**************************************************
+ *
+ * Function Prototypes
+ *
+ ***********************************************************/
+
+/* WAN link driver entry points. These are called by the WAN router module. */
+static int wan_xilinx_release(sdla_t*, struct ifnet*);
+
+/* Network device interface */
+static int wan_xilinx_up (struct ifnet*);
+static int wan_xilinx_down(struct ifnet*);
+static int wan_xilinx_ioctl(struct ifnet*, int cmd, struct ifreq*);
+static int wan_xilinx_send (struct mbuf*, struct ifnet*);
+
+static void handle_front_end_state(void*);
+static void enable_timer(void*);
+
+/* Miscellaneous Functions */
+static void port_set_state (sdla_t*, int);
+
+/* Interrupt handlers */
+static void wp_xilinx_isr (sdla_t*);
+
+/* Miscellaneous functions */
+static int process_udp_mgmt_pkt(sdla_t*, struct ifnet*,
+ xilinx_softc_t*,
+ int);
+/* Bottom half handlers */
+static void xilinx_process_packet(xilinx_softc_t*);
+
+static int xilinx_chip_configure(sdla_t*);
+static int xilinx_chip_unconfigure(sdla_t*);
+static int xilinx_dev_configure(sdla_t*, xilinx_softc_t*);
+static void xilinx_dev_unconfigure(sdla_t*, xilinx_softc_t*);
+static int xilinx_dma_rx(sdla_t*, xilinx_softc_t*);
+static void xilinx_dev_enable(sdla_t*, xilinx_softc_t*);
+static void xilinx_dev_close(sdla_t*, xilinx_softc_t*);
+static int xilinx_dma_tx (sdla_t*, xilinx_softc_t*);
+static void xilinx_dma_tx_complete (sdla_t*, xilinx_softc_t*);
+static void xilinx_dma_rx_complete (sdla_t*, xilinx_softc_t*);
+static void xilinx_dma_max_logic_ch(sdla_t*);
+static int xilinx_init_rx_dev_fifo(sdla_t*, xilinx_softc_t*, unsigned char);
+static void xilinx_init_tx_dma_descr(sdla_t*, xilinx_softc_t*);
+static int xilinx_init_tx_dev_fifo(sdla_t*, xilinx_softc_t*, unsigned char);
+static void xilinx_tx_post_complete (sdla_t*, xilinx_softc_t*, struct mbuf*);
+static void xilinx_rx_post_complete (sdla_t*, xilinx_softc_t*,
+ struct mbuf*,
+ struct mbuf**,
+ unsigned char*);
+
+
+static char request_xilinx_logical_channel_num (sdla_t*, xilinx_softc_t*, long*);
+static void free_xilinx_logical_channel_num (sdla_t*, int);
+
+
+static unsigned char read_cpld(sdla_t*, unsigned short);
+static unsigned char write_cpld(sdla_t*, unsigned short,unsigned char);
+
+static void front_end_interrupt(sdla_t*, unsigned long);
+static void enable_data_error_intr(sdla_t*);
+static void disable_data_error_intr(sdla_t*, unsigned char);
+
+static void xilinx_tx_fifo_under_recover (sdla_t*, xilinx_softc_t*);
+
+static int xilinx_write_ctrl_hdlc(sdla_t*, u_int32_t, u_int8_t, u_int32_t);
+
+static int set_chan_state(sdla_t*, struct ifnet*, int);
+
+static int fifo_error_interrupt(sdla_t*, unsigned long);
+static int request_fifo_baddr_and_size(sdla_t*, xilinx_softc_t*);
+static int map_fifo_baddr_and_size(sdla_t*, unsigned char, unsigned char*);
+static int free_fifo_baddr_and_size (sdla_t*, xilinx_softc_t*);
+
+static void aft_red_led_ctrl(sdla_t*, int);
+static void aft_led_timer(void*);
+
+static int aft_alloc_rx_dma_buff(sdla_t*, xilinx_softc_t*, int);
+static int aft_init_requeue_free_m(xilinx_softc_t*, struct mbuf*);
+static int aft_core_ready(sdla_t*);
+
+/* TE1 Control registers */
+static WRITE_FRONT_END_REG_T write_front_end_reg;
+static READ_FRONT_END_REG_T read_front_end_reg;
+
+static void wan_ifmedia_sts(struct ifnet*, struct ifmediareq*);
+static int wan_ifmedia_upd(struct ifnet*);
+
+static void xilinx_delay(int sec)
+{
+#if 0
+ unsigned long timeout=ticks;
+ while ((ticks-timeout)<(sec*hz)){
+ schedule();
+ }
+#endif
+}
+
+/**SECTION*********************************************************
+ *
+ * Public Functions
+ *
+ ******************************************************************/
+
+/*============================================================================
+ * wan_xilinx_init -
+ *
+ */
+
+void* wan_xilinx_init (sdla_t* card)
+{
+ xilinx_softc_t *sc;
+ struct ifnet *ifp;
+
+ /* Verify configuration ID */
+ bit_clear((u_int8_t*)&card->critical, CARD_DOWN);
+
+ card->u.xilinx.num_of_ch = 0;
+ card->u.xilinx.mru_trans = 1500;
+ card->u.xilinx.dma_per_ch = 10;
+
+ /* TE1 Make special hardware initialization for T1/E1 board */
+
+ if (IS_TE1(&card->fe_te.te_cfg)){
+
+ card->write_front_end_reg = write_front_end_reg;
+ card->read_front_end_reg = read_front_end_reg;
+ card->te_enable_timer = enable_timer;
+ card->te_link_state = handle_front_end_state;
+ }else{
+ card->front_end_status = FE_CONNECTED;
+ }
+
+ /* WARNING: After this point the init function
+ * must return with 0. The following bind
+ * functions will cause problems if structures
+ * below are not initialized */
+
+ card->del_if = &wan_xilinx_release;
+ card->iface_up = &wan_xilinx_up;
+ card->iface_down = &wan_xilinx_down;
+ card->iface_send = &wan_xilinx_send;
+ card->iface_ioctl= &wan_xilinx_ioctl;
+
+ write_cpld(card,LED_CONTROL_REG,0x0E);
+
+ sdla_getcfg(card->hw, SDLA_BASEADDR, &card->u.xilinx.bar);
+
+ xilinx_delay(1);
+
+ timeout_set(&card->u.xilinx.led_timer, aft_led_timer, (void*)card);
+
+ /* allocate and initialize private data */
+ sc = malloc(sizeof(xilinx_softc_t), M_DEVBUF, M_NOWAIT);
+ if(sc == NULL){
+ return NULL;
+ }
+ memset(sc, 0, sizeof(xilinx_softc_t));
+ ifp = (struct ifnet*)&sc->common.ifp;
+ if (wanpipe_generic_register(card, ifp, card->devname)){
+ free(sc, M_DEVBUF);
+ return NULL;
+ }
+
+
+ strncpy(sc->if_name, ifp->if_xname, IFNAMSIZ);
+ ifp->if_softc = sc;
+ sc->common.card = card;
+ sc->first_time_slot=-1;
+ sc->time_slot_map = 0;
+
+ IFQ_SET_MAXLEN(&sc->wp_tx_free_list, MAX_TX_BUF);
+ sc->wp_tx_free_list.ifq_len = 0;
+ IFQ_SET_MAXLEN(&sc->wp_tx_pending_list, MAX_TX_BUF);
+ sc->wp_tx_pending_list.ifq_len = 0;
+ IFQ_SET_MAXLEN(&sc->wp_tx_complete_list, MAX_TX_BUF);
+ sc->wp_tx_complete_list.ifq_len = 0;
+ IFQ_SET_MAXLEN(&sc->wp_rx_free_list, MAX_RX_BUF);
+ sc->wp_rx_free_list.ifq_len = 0;
+ IFQ_SET_MAXLEN(&sc->wp_rx_complete_list, MAX_RX_BUF);
+ sc->wp_rx_complete_list.ifq_len = 0;
+
+ xilinx_delay(1);
+
+ ifmedia_init(&sc->common.ifm, 0, wan_ifmedia_upd, wan_ifmedia_sts);
+ if (IS_TE1(&card->fe_te.te_cfg)){
+ ifmedia_add(&sc->common.ifm, IFM_TDM|IFM_TDM_T1, 0, NULL);
+ ifmedia_add(&sc->common.ifm, IFM_TDM|IFM_TDM_T1_AMI, 0, NULL);
+ ifmedia_add(&sc->common.ifm, IFM_TDM|IFM_TDM_E1, 0, NULL);
+ ifmedia_add(&sc->common.ifm, IFM_TDM|IFM_TDM_E1_AMI, 0, NULL);
+ ifmedia_set(&sc->common.ifm, IFM_TDM|IFM_TDM_T1);
+ }else{
+ /* Currently we not support ifmedia types for other
+ ** front end types. */
+ }
+ return sc;
+}
+
+/*============================================================================
+ * wan_xilinx_release
+ *
+ *
+ */
+static int wan_xilinx_release (sdla_t* card, struct ifnet* ifp)
+{
+ xilinx_softc_t* sc = ifp->if_softc;
+
+ IF_PURGE(&sc->wp_rx_free_list);
+ IF_PURGE(&sc->wp_rx_complete_list);
+ IF_PURGE(&sc->wp_tx_free_list);
+ IF_PURGE(&sc->wp_tx_pending_list);
+
+ if (sc->tx_dma_addr && sc->tx_dma_len){
+ sc->tx_dma_addr=0;
+ sc->tx_dma_len=0;
+ }
+
+ if (sc->tx_dma_mbuf){
+ log(LOG_INFO, "freeing tx dma mbuf\n");
+ m_freem(sc->tx_dma_mbuf);
+ sc->tx_dma_mbuf=NULL;
+ }
+
+ if (sc->tx_idle_mbuf){
+ log(LOG_INFO, "freeing idle tx dma mbuf\n");
+ m_freem(sc->tx_idle_mbuf);
+ sc->tx_idle_mbuf=NULL;
+ }
+
+ if (sc->rx_dma_mbuf){
+ m_freem(sc->rx_dma_mbuf);
+ sc->rx_dma_mbuf=NULL;
+ }
+ wanpipe_generic_unregister(ifp);
+ ifp->if_softc = NULL;
+ free(sc, M_DEVBUF);
+ return 0;
+}
+
+static void wan_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmreq)
+{
+ wanpipe_common_t *common = (wanpipe_common_t*)ifp->if_softc;
+ struct ifmedia *ifm;
+
+ WAN_ASSERT1(common == NULL);
+ ifm = &common->ifm;
+ ifmreq->ifm_active = ifm->ifm_cur->ifm_media;
+ return;
+}
+
+static int wan_ifmedia_upd(struct ifnet *ifp)
+{
+ wanpipe_common_t *common = (wanpipe_common_t*)ifp->if_softc;
+ sdla_t *card;
+
+ WAN_ASSERT(common == NULL);
+ WAN_ASSERT(common->card == NULL);
+ card = (sdla_t*)common->card;
+ if (IS_TE1(&card->fe_te.te_cfg)){
+ return sdla_te_setcfg(card, &common->ifm);
+ }
+ return -EINVAL;
+}
+
+
+/**SECTION***********************************************************
+ *
+ * KERNEL Device Entry Interfaces
+ *
+ ********************************************************************/
+
+
+
+/*============================================================================
+ * wan_xilinx_up
+ *
+ */
+static int wan_xilinx_up (struct ifnet* ifp)
+{
+ xilinx_softc_t *sc = ifp->if_softc;
+ sdla_t *card = NULL;
+ struct timeval tv;
+ int err = 0;
+
+ WAN_ASSERT(sc == NULL);
+ WAN_ASSERT(sc->common.card == NULL);
+ card = (sdla_t*)sc->common.card;
+ if (card->state != WAN_DISCONNECTED){
+ return 0;
+ }
+ sc->time_slot_map = card->fe_te.te_cfg.active_ch;
+ sc->dma_mtu = xilinx_valid_mtu(ifp->if_mtu+100);
+ if (!sc->dma_mtu){
+ log(LOG_INFO, "%s:%s: Error invalid MTU %d\n",
+ card->devname,
+ sc->if_name,
+ ifp->if_mtu);
+ return -EINVAL;
+ }
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Allocating %d dma mbuf len=%d\n",
+ card->devname,
+ card->u.xilinx.dma_per_ch,
+ sc->dma_mtu);
+#endif
+ err=aft_alloc_rx_dma_buff(card, sc, card->u.xilinx.dma_per_ch);
+ if (err){
+ return -EINVAL;
+ }
+
+ err=xilinx_chip_configure(card);
+ if (err){
+ return -EINVAL;
+ }
+
+ card->isr = &wp_xilinx_isr;
+
+ err=xilinx_dev_configure(card, sc);
+ if (err){
+ xilinx_chip_unconfigure(card);
+ return -EINVAL;
+ }
+ xilinx_delay(1);
+
+ /* Initialize the router start time.
+ * Used by wanpipemon debugger to indicate
+ * how long has the interface been up */
+ microtime(&tv);
+ sc->router_start_time = tv.tv_sec;
+
+ xilinx_init_tx_dma_descr(card,sc);
+ xilinx_dev_enable(card,sc);
+
+ sc->ignore_modem=0x0F;
+ bit_clear((u_int8_t*)&card->critical, CARD_DOWN);
+ port_set_state(card, WAN_CONNECTING);
+ return err;
+}
+
+/*============================================================================
+ * wan_xilinx_down
+ *
+ */
+static int wan_xilinx_down (struct ifnet* ifp)
+{
+ xilinx_softc_t *sc = ifp->if_softc;
+ sdla_t *card = (sdla_t*)sc->common.card;
+ struct mbuf *m;
+ int s;
+
+ if (card->state == WAN_DISCONNECTED){
+ return 0;
+ }
+ xilinx_dev_close(card,sc);
+
+ /* Disable DMA ENGINE before we perform
+ * core reset. Otherwise, we will receive
+ * rx fifo errors on subsequent resetart. */
+ disable_data_error_intr(card,DEVICE_DOWN);
+
+ bit_set((u_int8_t*)&card->critical, CARD_DOWN);
+
+ timeout_del(&card->u.xilinx.led_timer);
+
+ /* TE1 - Unconfiging, only on shutdown */
+ if (IS_TE1(&card->fe_te.te_cfg)) {
+ sdla_te_unconfig(card);
+ }
+
+ s = splnet();
+
+ card->isr=NULL;
+
+ if (sc->tx_dma_addr && sc->tx_dma_len){
+ sc->tx_dma_addr=0;
+ sc->tx_dma_len=0;
+ }
+
+ if (sc->tx_dma_mbuf){
+ m_freem(sc->tx_dma_mbuf);
+ sc->tx_dma_mbuf=NULL;
+ }
+
+ if (sc->tx_idle_mbuf){
+ m_freem(sc->tx_idle_mbuf);
+ sc->tx_idle_mbuf=NULL;
+ }
+
+ /* If there is something left in rx_dma_buf, then
+ ** move it to rx_free_list. */
+ if (sc->rx_dma_mbuf){
+ m=sc->rx_dma_mbuf;
+ aft_init_requeue_free_m(sc, m);
+ sc->rx_dma_mbuf=NULL;
+ }
+ /* If there is something in rx_complete_list, then
+ ** move evething to rx_free_list. */
+ for(;;){
+ IF_DEQUEUE(&sc->wp_rx_complete_list, m);
+ if (m == NULL)
+ break;
+ IF_ENQUEUE(&sc->wp_rx_free_list, m);
+ }
+
+ splx(s);
+
+ DELAY(10);
+
+ xilinx_dev_unconfigure(card, sc);
+ xilinx_chip_unconfigure(card);
+
+ port_set_state(card, WAN_DISCONNECTED);
+ sc->ignore_modem=0x00;
+ return 0;
+}
+
+/*============================================================================
+ * wan_xilinx_send
+ *
+ *
+ */
+static int wan_xilinx_send (struct mbuf* m, struct ifnet* ifp)
+{
+
+ xilinx_softc_t *sc = ifp->if_softc;
+ sdla_t *card = (sdla_t*)sc->common.card;
+
+ /* Mark interface as busy. The kernel will not
+ * attempt to send any more packets until we clear
+ * this condition */
+
+ if (m == NULL){
+ /* This should never happen. Just a sanity check.
+ */
+ return -EINVAL;
+ }
+
+ if (card->state != WAN_CONNECTED){
+ /* The card is still not ready to transmit... drop this packet! */
+ m_freem(m);
+ return -EINVAL;
+
+ }else {
+
+ if (IF_QFULL(&sc->wp_tx_pending_list)){
+ int err;
+#if defined(DEBUG_TX)
+ log(LOG_INFO, "%s: Tx pending queue FULL\n",
+ ifp->if_xname);
+#endif
+ /* TX pending queue is full. Try to send packet
+ ** from tx_pending queue (first) */
+ err = xilinx_dma_tx(card,sc);
+ if (!err && !IF_QFULL(&sc->wp_tx_pending_list)){
+ /* On success, we have place for the new
+ ** tx packet, try to send it now! */
+ goto wan_xilinx_dma_tx_try;
+ }
+ /* Tx pedning queue is full. I can't accept new
+ ** tx packet, drop this packet and set interface
+ ** queue to OACTIVE */
+ m_freem(m);
+ ifp->if_flags |= IFF_OACTIVE;
+ return -EBUSY;
+ }else{
+wan_xilinx_dma_tx_try:
+ IF_ENQUEUE(&sc->wp_tx_pending_list, m);
+ xilinx_dma_tx(card,sc);
+ }
+ }
+
+ return 0;
+}
+
+
+
+/*========================================================================
+ *
+ * wan_xilinx_ioctl
+ *
+ *
+ */
+static int
+wan_xilinx_ioctl(struct ifnet *ifp, int cmd, struct ifreq *ifr)
+{
+ xilinx_softc_t *sc= (xilinx_softc_t*)ifp->if_softc;
+ struct mbuf *m;
+ sdla_t *card;
+ wan_udp_pkt_t *wan_udp_pkt;
+ int err=0;
+
+ if (!sc){
+ return -ENODEV;
+ }
+ card=(sdla_t*)sc->common.card;
+
+ switch(cmd)
+ {
+ case SIOC_WANPIPE_PIPEMON:
+
+ if (IF_QFULL(&sc->udp_queue)){
+ return -EBUSY;
+ }
+
+ /* For performance reasons test the critical
+ * here before spin lock */
+ if (bit_test((u_int8_t*)&card->in_isr, 0)){
+ return -EBUSY;
+ }
+
+ m = wan_mbuf_alloc();
+ if (m == NULL){
+ return -ENOMEM;
+ }
+ wan_udp_pkt = mtod(m, wan_udp_pkt_t*);
+ if (copyin(ifr->ifr_data, &wan_udp_pkt->wan_udp_hdr,sizeof(wan_udp_hdr_t))){
+ m_freem(m);
+ return -EFAULT;
+ }
+ IF_ENQUEUE(&sc->udp_queue, m);
+
+ process_udp_mgmt_pkt(card,ifp,sc,1);
+
+ if (copyout(&wan_udp_pkt->wan_udp_hdr,ifr->ifr_data, sizeof(wan_udp_hdr_t))){
+ m_freem(m);
+ return -EFAULT;
+ }
+
+ IF_DEQUEUE(&sc->udp_queue, m);
+ m_freem(m);
+ return 0;
+
+ default:
+ if (card->ioctl){
+ err = card->ioctl(ifp, cmd, ifr);
+ }
+ break;
+ }
+
+ return err;
+}
+
+/*=============================================================================
+ * process_udp_mgmt_pkt
+ *
+ * Process all "wanpipemon" debugger commands. This function
+ * performs all debugging tasks:
+ *
+ * Line Tracing
+ * Line/Hardware Statistics
+ * Protocol Statistics
+ *
+ * "wanpipemon" utility is a user-space program that
+ * is used to debug the WANPIPE product.
+ *
+ */
+#if 1
+static int process_udp_mgmt_pkt(sdla_t* card, struct ifnet* ifp,
+ xilinx_softc_t* sc, int local_dev )
+{
+ struct mbuf *m;
+ unsigned short buffer_length;
+ wan_udp_pkt_t *wan_udp_pkt;
+ wan_trace_t *trace_info=NULL;
+ struct timeval tv;
+
+ IF_POLL(&sc->udp_queue, m);
+ if (m == NULL){
+ return -EINVAL;
+ }
+ wan_udp_pkt = mtod(m, wan_udp_pkt_t *);
+ trace_info=&sc->trace_info;
+
+ {
+
+ struct mbuf *m0;
+
+ wan_udp_pkt->wan_udp_opp_flag = 0;
+
+ switch(wan_udp_pkt->wan_udp_command) {
+
+ case READ_CONFIGURATION:
+ case READ_CODE_VERSION:
+ wan_udp_pkt->wan_udp_return_code = 0;
+ wan_udp_pkt->wan_udp_data_len=0;
+ break;
+
+
+ case ENABLE_TRACING:
+
+ wan_udp_pkt->wan_udp_return_code = WAN_CMD_OK;
+ wan_udp_pkt->wan_udp_data_len = 0;
+
+ if (!bit_test((u_int8_t*)&trace_info->tracing_enabled, 0)){
+
+ trace_info->trace_timeout = ticks;
+
+ IF_PURGE(&trace_info->ifq);
+ if (wan_udp_pkt->wan_udp_data[0] == 0){
+ bit_clear((u_int8_t*)&trace_info->tracing_enabled, 1);
+ log(LOG_INFO, "%s: ADSL L3 trace enabled!\n",
+ card->devname);
+ }else if (wan_udp_pkt->wan_udp_data[0] == 1){
+ bit_clear((u_int8_t*)&trace_info->tracing_enabled,2 );
+ bit_set((u_int8_t*)&trace_info->tracing_enabled,1);
+ log(LOG_INFO, "%s: ADSL L2 trace enabled!\n",
+ card->devname);
+ }else{
+ bit_clear((u_int8_t*)&trace_info->tracing_enabled, 1);
+ bit_set((u_int8_t*)&trace_info->tracing_enabled,2);
+ log(LOG_INFO, "%s: ADSL L1 trace enabled!\n",
+ card->devname);
+ }
+ bit_set ((u_int8_t*)&trace_info->tracing_enabled, 0);
+
+ }else{
+ log(LOG_INFO, "%s: Error: AFT trace running!\n",
+ card->devname);
+ wan_udp_pkt->wan_udp_return_code = 2;
+ }
+
+ break;
+
+ case DISABLE_TRACING:
+
+ wan_udp_pkt->wan_udp_return_code = WAN_CMD_OK;
+
+ if(bit_test((u_int8_t*)&trace_info->tracing_enabled, 0)) {
+
+ bit_clear((u_int8_t*)&trace_info->tracing_enabled, 0);
+ bit_clear((u_int8_t*)&trace_info->tracing_enabled, 1);
+ bit_clear((u_int8_t*)&trace_info->tracing_enabled, 2);
+ IF_PURGE(&trace_info->ifq);
+ log(LOG_INFO, "%s: Disabling ADSL trace\n",
+ card->devname);
+
+ }else{
+ /* set return code to line trace already
+ disabled */
+ wan_udp_pkt->wan_udp_return_code = 1;
+ }
+
+ break;
+
+ case GET_TRACE_INFO:
+
+ if(bit_test((u_int8_t*)&trace_info->tracing_enabled, 0)){
+ trace_info->trace_timeout = ticks;
+ }else{
+ log(LOG_INFO, "%s: Error AFT trace not enabled\n",
+ card->devname);
+ /* set return code */
+ wan_udp_pkt->wan_udp_return_code = 1;
+ break;
+ }
+
+ buffer_length = 0;
+ wan_udp_pkt->wan_udp_aft_num_frames = 0;
+ wan_udp_pkt->wan_udp_aft_ismoredata = 0;
+
+ while (!IF_IS_EMPTY(&trace_info->ifq)){
+ IF_POLL(&trace_info->ifq, m0);
+ if (m0 == NULL){
+ log(LOG_INFO, "%s: No more trace packets in trace queue!\n",
+ card->devname);
+ break;
+ }
+ if ((WAN_MAX_DATA_SIZE - buffer_length) < m0->m_pkthdr.len){
+ /* indicate there are more frames on board & exit */
+ wan_udp_pkt->wan_udp_aft_ismoredata = 0x01;
+ break;
+ }
+
+ m_copydata(m0,
+ 0,
+ m0->m_pkthdr.len,
+ &wan_udp_pkt->wan_udp_data[buffer_length]);
+ buffer_length += m0->m_pkthdr.len;
+ IF_DEQUEUE(&trace_info->ifq, m0);
+ if (m0){
+ m_freem(m0);
+ }
+ wan_udp_pkt->wan_udp_aft_num_frames++;
+ }
+ /* set the data length and return code */
+ wan_udp_pkt->wan_udp_data_len = buffer_length;
+ wan_udp_pkt->wan_udp_return_code = WAN_CMD_OK;
+ break;
+
+ case ROUTER_UP_TIME:
+ microtime(&tv);
+ sc->router_up_time = tv.tv_sec;
+ sc->router_up_time -= sc->router_start_time;
+ *(unsigned long *)&wan_udp_pkt->wan_udp_data =
+ sc->router_up_time;
+ wan_udp_pkt->wan_udp_data_len = sizeof(unsigned long);
+ wan_udp_pkt->wan_udp_return_code = 0;
+ break;
+
+ case WAN_GET_MEDIA_TYPE:
+ case WAN_FE_GET_STAT:
+ case WAN_FE_SET_LB_MODE:
+ case WAN_FE_FLUSH_PMON:
+ case WAN_FE_GET_CFG:
+
+ if (IS_TE1(&card->fe_te.te_cfg)){
+ sdla_te_udp(card,
+ &wan_udp_pkt->wan_udp_cmd,
+ &wan_udp_pkt->wan_udp_data[0]);
+ }else{
+ if (wan_udp_pkt->wan_udp_command == WAN_GET_MEDIA_TYPE){
+ wan_udp_pkt->wan_udp_data_len = sizeof(unsigned char);
+ wan_udp_pkt->wan_udp_return_code = WAN_CMD_OK;
+ }else{
+ wan_udp_pkt->wan_udp_return_code = WAN_UDP_INVALID_CMD;
+ }
+ }
+ break;
+
+
+
+ case WAN_GET_PROTOCOL:
+ wan_udp_pkt->wan_udp_aft_num_frames = WANCONFIG_AFT;
+ wan_udp_pkt->wan_udp_return_code = WAN_CMD_OK;
+ wan_udp_pkt->wan_udp_data_len = 1;
+ break;
+
+ case WAN_GET_PLATFORM:
+ wan_udp_pkt->wan_udp_data[0] = WAN_PLATFORM_ID;
+ wan_udp_pkt->wan_udp_return_code = WAN_CMD_OK;
+ wan_udp_pkt->wan_udp_data_len = 1;
+ break;
+
+ default:
+ wan_udp_pkt->wan_udp_data_len = 0;
+ wan_udp_pkt->wan_udp_return_code = 0xCD;
+
+ log(LOG_INFO, "%s: Warning, Illegal UDP command attempted from network: %x\n",
+ card->devname,wan_udp_pkt->wan_udp_command);
+ break;
+ } /* end of switch */
+ } /* end of else */
+
+ wan_udp_pkt->wan_udp_request_reply = UDPMGMT_REPLY;
+ return 1;
+
+}
+#endif
+
+/**SECTION**********************************************************
+ *
+ * FIRMWARE Specific Interface Functions
+ *
+ *******************************************************************/
+
+
+/*============================================================================
+ * xilinx_chip_configure
+ *
+ *
+ */
+
+static int xilinx_chip_configure(sdla_t *card)
+{
+ u_int32_t reg,tmp;
+ int err=0;
+ u_int16_t adapter_type,adptr_security;
+
+#if defined(DEBUG_INIT)
+ log(LOG_DEBUG, "Xilinx Chip Configuration. -- \n");
+#endif
+ xilinx_delay(1);
+
+ sdla_bus_read_4(card->hw,XILINX_CHIP_CFG_REG,&reg);
+
+ /* Configure for T1 or E1 front end */
+ if (IS_T1(&card->fe_te.te_cfg)){
+ card->u.xilinx.num_of_time_slots=NUM_OF_T1_CHANNELS;
+ bit_clear((u_int8_t*)&reg, INTERFACE_TYPE_T1_E1_BIT);
+ bit_set((u_int8_t*)&reg, FRONT_END_FRAME_FLAG_ENABLE_BIT);
+ }else if (IS_E1(&card->fe_te.te_cfg)){
+ card->u.xilinx.num_of_time_slots=NUM_OF_E1_CHANNELS;
+ bit_set((u_int8_t*)&reg, INTERFACE_TYPE_T1_E1_BIT);
+ bit_set((u_int8_t*)&reg, FRONT_END_FRAME_FLAG_ENABLE_BIT);
+ }else{
+ log(LOG_INFO, "%s: Error: Xilinx doesn't support non T1/E1 interface!\n",
+ card->devname);
+ return -EINVAL;
+ }
+
+ sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg);
+
+ DELAY(10000);
+
+ /* Reset PMC */
+ sdla_bus_read_4(card->hw,XILINX_CHIP_CFG_REG,&reg);
+ bit_clear((u_int8_t*)&reg, FRONT_END_RESET_BIT);
+ sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg);
+ DELAY(1000);
+
+ bit_set((u_int8_t*)&reg, FRONT_END_RESET_BIT);
+ sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg);
+ DELAY(100);
+
+#if defined(DEBUG_INIT)
+ log(LOG_DEBUG, "--- Chip Reset. -- \n");
+#endif
+
+ /* Reset Chip Core */
+ sdla_bus_read_4(card->hw,XILINX_CHIP_CFG_REG, &reg);
+ bit_set((u_int8_t*)&reg, CHIP_RESET_BIT);
+ sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg);
+
+ DELAY(100);
+
+ /* Disable the chip/hdlc reset condition */
+ bit_clear((u_int8_t*)&reg, CHIP_RESET_BIT);
+
+ /* Disable ALL chip interrupts */
+ bit_clear((u_int8_t*)&reg, GLOBAL_INTR_ENABLE_BIT);
+ bit_clear((u_int8_t*)&reg, ERROR_INTR_ENABLE_BIT);
+ bit_clear((u_int8_t*)&reg, FRONT_END_INTR_ENABLE_BIT);
+
+ sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg);
+
+ xilinx_delay(1);
+
+ sdla_getcfg(card->hw, SDLA_ADAPTERTYPE, &adapter_type);
+ DELAY(100);
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Hardware Adapter Type 0x%X\n",
+ card->devname,adapter_type);
+#endif
+
+ adptr_security = read_cpld(card,SECURITY_CPLD_REG);
+ adptr_security = adptr_security >> SECURITY_CPLD_SHIFT;
+ adptr_security = adptr_security & SECURITY_CPLD_MASK;
+
+#if defined(DEBUG_INIT)
+ switch(adptr_security){
+ case SECURITY_1LINE_UNCH:
+ log(LOG_INFO, "%s: Security 1 Line UnCh\n",
+ card->devname);
+ break;
+ case SECURITY_1LINE_CH:
+ log(LOG_INFO, "%s: Security 1 Line Ch\n",
+ card->devname);
+ break;
+ case SECURITY_2LINE_UNCH:
+ log(LOG_INFO, "%s: Security 2 Line UnCh\n",
+ card->devname);
+ break;
+ case SECURITY_2LINE_CH:
+ log(LOG_INFO, "%s: Security 2 Line Ch\n",
+ card->devname);
+ break;
+ default:
+ log(LOG_INFO, "%s: Error Invalid Security ID=0x%X\n",
+ card->devname,adptr_security);
+ /*return -EINVAL;*/
+ }
+#endif
+
+ /* Turn off Onboard RED LED */
+ sdla_bus_read_4(card->hw,XILINX_CHIP_CFG_REG,&reg);
+ bit_set((u_int8_t*)&reg, XILINX_RED_LED);
+ sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg);
+ DELAY(10);
+
+ err=aft_core_ready(card);
+ if (err != 0){
+ log(LOG_INFO, "%s: WARNING: HDLC Core Not Ready: B4 TE CFG!\n",
+ card->devname);
+
+ }
+
+ log(LOG_INFO, "%s: Configuring A101 PMC T1/E1/J1 Front End\n",
+ card->devname);
+
+ if (sdla_te_config(card)){
+ log(LOG_INFO, "%s: Failed %s configuratoin!\n",
+ card->devname,
+ IS_T1(&card->fe_te.te_cfg)?"T1":"E1");
+ return -EINVAL;
+ }
+
+ xilinx_delay(1);
+
+ err=aft_core_ready(card);
+ if (err != 0){
+ log(LOG_INFO, "%s: Error: HDLC Core Not Ready!\n",
+ card->devname);
+
+ sdla_bus_read_4(card->hw,XILINX_CHIP_CFG_REG, &reg);
+
+ /* Disable the chip/hdlc reset condition */
+ bit_set((u_int8_t*)&reg, CHIP_RESET_BIT);
+
+ sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg);
+ return err;
+ } else{
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: HDLC Core Ready 0x%08X\n",
+ card->devname,reg);
+#endif
+ }
+
+ xilinx_delay(1);
+
+ /* Setup global DMA parameters */
+ reg=0;
+ reg|=(XILINX_DMA_SIZE << DMA_SIZE_BIT_SHIFT);
+ reg|=(XILINX_DMA_FIFO_UP << DMA_FIFO_HI_MARK_BIT_SHIFT);
+ reg|=(XILINX_DMA_FIFO_LO << DMA_FIFO_LO_MARK_BIT_SHIFT);
+
+ /* Enable global DMA engine and set to default
+ * number of active channels. Note: this value will
+ * change in dev configuration */
+ reg|=(XILINX_DEFLT_ACTIVE_CH << DMA_ACTIVE_CHANNEL_BIT_SHIFT);
+ bit_set((u_int8_t*)&reg, DMA_ENGINE_ENABLE_BIT);
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "--- Setup DMA control Reg. -- \n");
+#endif
+
+ sdla_bus_write_4(card->hw,XILINX_DMA_CONTROL_REG,reg);
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "--- Tx/Rx global enable. -- \n");
+#endif
+
+ xilinx_delay(1);
+
+ reg=0;
+ sdla_bus_write_4(card->hw,XILINX_TIMESLOT_HDLC_CHAN_REG,reg);
+
+ /* Clear interrupt pending registers befor first interrupt enable */
+ sdla_bus_read_4(card->hw, XILINX_DMA_RX_INTR_PENDING_REG, &tmp);
+ sdla_bus_read_4(card->hw, XILINX_DMA_TX_INTR_PENDING_REG, &tmp);
+ sdla_bus_read_4(card->hw,XILINX_HDLC_RX_INTR_PENDING_REG, &tmp);
+ sdla_bus_read_4(card->hw,XILINX_HDLC_TX_INTR_PENDING_REG, &tmp);
+ sdla_bus_read_4(card->hw,XILINX_CHIP_CFG_REG, (u_int32_t*)&reg);
+ if (bit_test((u_int8_t*)&reg, DMA_INTR_FLAG)){
+ log(LOG_INFO, "%s: Error: Active DMA Interrupt Pending. !\n",
+ card->devname);
+
+ reg = 0;
+ /* Disable the chip/hdlc reset condition */
+ bit_set((u_int8_t*)&reg, CHIP_RESET_BIT);
+ sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg);
+ return err;
+ }
+ if (bit_test((u_int8_t*)&reg, ERROR_INTR_FLAG)){
+ log(LOG_INFO, "%s: Error: Active Error Interrupt Pending. !\n",
+ card->devname);
+
+ reg = 0;
+ /* Disable the chip/hdlc reset condition */
+ bit_set((u_int8_t*)&reg, CHIP_RESET_BIT);
+ sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg);
+ return err;
+ }
+
+
+ /* Alawys disable global data and error
+ * interrupts */
+ bit_clear((u_int8_t*)&reg, GLOBAL_INTR_ENABLE_BIT);
+ bit_clear((u_int8_t*)&reg, ERROR_INTR_ENABLE_BIT);
+
+ /* Always enable the front end interrupt */
+ bit_set((u_int8_t*)&reg, FRONT_END_INTR_ENABLE_BIT);
+
+#if defined(DEBUG_INIT)
+ log(LOG_DEBUG, "--- Set Global Interrupts (0x%X)-- \n",reg);
+#endif
+
+ xilinx_delay(1);
+
+
+ sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg);
+
+ return err;
+}
+
+/*============================================================================
+ * xilinx_chip_unconfigure
+ *
+ *
+ */
+
+static int xilinx_chip_unconfigure(sdla_t *card)
+{
+ u_int32_t reg = 0;
+
+ sdla_bus_write_4(card->hw,XILINX_TIMESLOT_HDLC_CHAN_REG,reg);
+ sdla_bus_read_4(card->hw,XILINX_CHIP_CFG_REG, &reg);
+ /* Enable the chip/hdlc reset condition */
+ reg=0;
+ bit_set((u_int8_t*)&reg, CHIP_RESET_BIT);
+
+ sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg);
+ return 0;
+}
+
+
+/*============================================================================
+ * xilinx_dev_configure
+ *
+ *
+ */
+
+static int xilinx_dev_configure(sdla_t *card, xilinx_softc_t *sc)
+{
+ u_int32_t reg;
+ long free_logic_ch,i;
+
+ sc->logic_ch_num=-1;
+
+ if (!IS_TE1(&card->fe_te.te_cfg)){
+ return -EINVAL;
+ }
+
+ if (IS_E1(&card->fe_te.te_cfg)){
+ log(LOG_DEBUG, "%s: Time Slot Orig 0x%lX Shifted 0x%lX\n",
+ sc->if_name,
+ sc->time_slot_map,
+ sc->time_slot_map<<1);
+ sc->time_slot_map=sc->time_slot_map<<1;
+ bit_clear((u_int8_t*)&sc->time_slot_map, 0);
+ }
+
+ /* Channel definition section. If not channels defined
+ * return error */
+ if (sc->time_slot_map == 0){
+ log(LOG_INFO, "%s: Invalid Channel Selection 0x%lX\n",
+ card->devname,sc->time_slot_map);
+ return -EINVAL;
+ }
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s:%s: Active channels = 0x%lX\n",
+ card->devname,sc->if_name,sc->time_slot_map);
+#endif
+ xilinx_delay(1);
+
+ /* Check that the time slot is not being used. If it is
+ * stop the interface setup. Notice, though we proceed
+ * to check for all timeslots before we start binding
+ * the channels in. This way, we don't have to go back
+ * and clean the time_slot_map */
+ for (i=0;i<card->u.xilinx.num_of_time_slots;i++){
+ if (bit_test((u_int8_t*)&sc->time_slot_map, i)){
+
+ if (sc->first_time_slot == -1){
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Setting first time slot to %ld\n",
+ card->devname,i);
+#endif
+ sc->first_time_slot=i;
+ }
+
+#if defined(DEBUG_INIT)
+ log(LOG_DEBUG, "%s: Configuring %s for timeslot %ld\n",
+ card->devname, sc->if_name,
+ IS_E1(&card->fe_te.te_cfg)?i:i+1);
+#endif
+ if (bit_test((u_int8_t*)&card->u.xilinx.time_slot_map, i)){
+ log(LOG_INFO, "%s: Channel/Time Slot resource conflict!\n",
+ card->devname);
+ log(LOG_INFO, "%s: %s: Channel/Time Slot %ld, aready in use!\n",
+ card->devname,sc->if_name,(i+1));
+
+ return -EEXIST;
+ }
+
+ /* Calculate the number of timeslots for this
+ * interface */
+ ++sc->num_of_time_slots;
+ }
+ }
+
+ xilinx_delay(1);
+
+ sc->logic_ch_num=request_xilinx_logical_channel_num(card, sc, &free_logic_ch);
+ if (sc->logic_ch_num == -1){
+ return -EBUSY;
+ }
+
+ xilinx_delay(1);
+
+ for (i=0;i<card->u.xilinx.num_of_time_slots;i++){
+ if (bit_test((u_int8_t*)&sc->time_slot_map, i)){
+
+ bit_set((u_int8_t*)&card->u.xilinx.time_slot_map, i);
+
+ sdla_bus_read_4(card->hw, XILINX_TIMESLOT_HDLC_CHAN_REG, &reg);
+ reg&=~TIMESLOT_BIT_MASK;
+
+ /*FIXME do not hardcode !*/
+ reg&= HDLC_LCH_TIMESLOT_MASK; /* mask not valid bits */
+
+
+ /* Select a Timeslot for configuration */
+ sdla_bus_write_4(card->hw,
+ XILINX_TIMESLOT_HDLC_CHAN_REG,
+ (reg|(i<<TIMESLOT_BIT_SHIFT)));
+
+
+ reg=sc->logic_ch_num&CONTROL_RAM_DATA_MASK;
+
+#ifdef TRUE_FIFO_SIZE
+ reg|=(sc->fifo_size_code&HDLC_FIFO_SIZE_MASK)<<HDLC_FIFO_SIZE_SHIFT;
+#else
+
+ reg|=(HARD_FIFO_CODE&HDLC_FIFO_SIZE_MASK)<<HDLC_FIFO_SIZE_SHIFT;
+#endif
+
+ reg|=(sc->fifo_base_addr&HDLC_FIFO_BASE_ADDR_MASK)<<
+ HDLC_FIFO_BASE_ADDR_SHIFT;
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "Setting Timeslot %ld to logic ch %ld Reg=0x%X\n",
+ i, sc->logic_ch_num,reg);
+#endif
+
+ xilinx_write_ctrl_hdlc(card,
+ i,
+ XILINX_CONTROL_RAM_ACCESS_BUF,
+ reg);
+
+ }
+ }
+
+ if (free_logic_ch != -1){
+
+ char free_ch_used=0;
+
+ for (i=0;i<card->u.xilinx.num_of_time_slots;i++){
+ if (!bit_test((u_int8_t*)&card->u.xilinx.time_slot_map, i)){
+
+ sdla_bus_read_4(card->hw,
+ XILINX_TIMESLOT_HDLC_CHAN_REG,
+ &reg);
+
+ reg&=~TIMESLOT_BIT_MASK;
+ reg&= HDLC_LCH_TIMESLOT_MASK; /* mask not valid bits */
+
+ /* Select a Timeslot for configuration */
+ sdla_bus_write_4(card->hw,
+ XILINX_TIMESLOT_HDLC_CHAN_REG,
+ (reg|(i<<TIMESLOT_BIT_SHIFT)));
+
+
+ reg=free_logic_ch&CONTROL_RAM_DATA_MASK;
+
+ /* For the rest of the unused logic channels
+ * bind them to timeslot 31 and set the fifo
+ * size to 32 byte = Code=0x00 */
+
+ reg|=(FIFO_32B&HDLC_FIFO_SIZE_MASK)<<HDLC_FIFO_SIZE_SHIFT;
+
+ reg|=(free_logic_ch&HDLC_FIFO_BASE_ADDR_MASK)<<
+ HDLC_FIFO_BASE_ADDR_SHIFT;
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "Setting Timeslot %ld to free logic ch %ld Reg=0x%X\n",
+ i, free_logic_ch,reg);
+#endif
+ xilinx_write_ctrl_hdlc(card,
+ i,
+ XILINX_CONTROL_RAM_ACCESS_BUF,
+ reg);
+
+ free_ch_used=1;
+ }
+ }
+
+
+ /* We must check if the free logic has been bound
+ * to any timeslots */
+ if (free_ch_used){
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Setting Free CH %ld to idle\n",
+ sc->if_name,free_logic_ch);
+#endif
+ xilinx_delay(1);
+
+ /* Setup the free logic channel as IDLE */
+
+ sdla_bus_read_4(card->hw, XILINX_TIMESLOT_HDLC_CHAN_REG, &reg);
+
+ reg&=~HDLC_LOGIC_CH_BIT_MASK;
+ reg&=HDLC_LCH_TIMESLOT_MASK; /* mask not valid bits */
+
+ sdla_bus_write_4(card->hw,
+ XILINX_TIMESLOT_HDLC_CHAN_REG,
+ (reg|(free_logic_ch&HDLC_LOGIC_CH_BIT_MASK)));
+
+ reg=0;
+ bit_clear((u_int8_t*)&reg, HDLC_RX_PROT_DISABLE_BIT);
+ bit_clear((u_int8_t*)&reg, HDLC_TX_PROT_DISABLE_BIT);
+
+ bit_set((u_int8_t*)&reg, HDLC_RX_ADDR_RECOGN_DIS_BIT);
+
+ xilinx_write_ctrl_hdlc(card,
+ sc->first_time_slot,
+ XILINX_HDLC_CONTROL_REG,
+ reg);
+ }
+ }
+
+ /* Select an HDLC logic channel for configuration */
+ sdla_bus_read_4(card->hw, XILINX_TIMESLOT_HDLC_CHAN_REG, &reg);
+
+ reg&=~HDLC_LOGIC_CH_BIT_MASK;
+ reg&= HDLC_LCH_TIMESLOT_MASK; /* mask not valid bits */
+
+ sdla_bus_write_4(card->hw,
+ XILINX_TIMESLOT_HDLC_CHAN_REG,
+ (reg|(sc->logic_ch_num&HDLC_LOGIC_CH_BIT_MASK)));
+
+ reg=0;
+
+ /* HDLC engine is enabled on the above logical channels */
+ bit_clear((u_int8_t*)&reg, HDLC_RX_PROT_DISABLE_BIT);
+ bit_clear((u_int8_t*)&reg, HDLC_TX_PROT_DISABLE_BIT);
+
+ bit_set((u_int8_t*)&reg, HDLC_TX_CHAN_ENABLE_BIT);
+ bit_set((u_int8_t*)&reg, HDLC_RX_ADDR_RECOGN_DIS_BIT);
+
+ xilinx_write_ctrl_hdlc(card,
+ sc->first_time_slot,
+ XILINX_HDLC_CONTROL_REG,
+ reg);
+
+ return 0;
+}
+
+
+static void xilinx_dev_unconfigure(sdla_t *card, xilinx_softc_t *sc)
+{
+ u_int32_t reg;
+ int i, s;
+
+#if defined(DEBUG_INIT)
+ log(LOG_DEBUG, "\n-- Unconfigure Xilinx. --\n");
+#endif
+
+ /* Select an HDLC logic channel for configuration */
+ if (sc->logic_ch_num != -1){
+
+ sdla_bus_read_4(card->hw,XILINX_TIMESLOT_HDLC_CHAN_REG, &reg);
+ reg&=~HDLC_LOGIC_CH_BIT_MASK;
+ reg&= HDLC_LCH_TIMESLOT_MASK; /* mask not valid bits */
+
+ sdla_bus_write_4(card->hw,
+ XILINX_TIMESLOT_HDLC_CHAN_REG,
+ (reg|(sc->logic_ch_num&HDLC_LOGIC_CH_BIT_MASK)));
+
+
+ reg=0x00020000;
+ xilinx_write_ctrl_hdlc(card,
+ sc->first_time_slot,
+ XILINX_HDLC_CONTROL_REG,
+ reg);
+
+
+ for (i=0;i<card->u.xilinx.num_of_time_slots;i++){
+ if (bit_test((u_int8_t*)&sc->time_slot_map, i)){
+
+ sdla_bus_read_4(card->hw, XILINX_TIMESLOT_HDLC_CHAN_REG, &reg);
+ reg&=~TIMESLOT_BIT_MASK;
+ reg&= HDLC_LCH_TIMESLOT_MASK; /* mask not valid bits */
+
+ /* Select a Timeslot for configuration */
+ sdla_bus_write_4(card->hw,
+ XILINX_TIMESLOT_HDLC_CHAN_REG,
+ (reg|(i<<TIMESLOT_BIT_SHIFT)));
+
+
+ reg=31&CONTROL_RAM_DATA_MASK;
+
+ reg|=(FIFO_32B&HDLC_FIFO_SIZE_MASK)<<HDLC_FIFO_SIZE_SHIFT;
+ reg|=(31&HDLC_FIFO_BASE_ADDR_MASK)<<
+ HDLC_FIFO_BASE_ADDR_SHIFT;
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "Setting Timeslot %d to logic ch %d Reg=0x%X\n",
+ i, 31 ,reg);
+#endif
+ xilinx_write_ctrl_hdlc(card,
+ i,
+ XILINX_CONTROL_RAM_ACCESS_BUF,
+ reg);
+ }
+ }
+
+ /* Lock to protect the logic ch map to
+ * sc device array */
+ s = splnet();
+ free_xilinx_logical_channel_num(card,sc->logic_ch_num);
+ for (i=0;i<card->u.xilinx.num_of_time_slots;i++){
+ if (bit_test((u_int8_t*)&sc->time_slot_map, i)){
+ --sc->num_of_time_slots;
+ }
+ }
+ free_fifo_baddr_and_size(card,sc);
+ splx(s);
+
+ sc->logic_ch_num=-1;
+
+ for (i=0;i<card->u.xilinx.num_of_time_slots;i++){
+ if (bit_test((u_int8_t*)&sc->time_slot_map, i)){
+ bit_clear((u_int8_t*)&card->u.xilinx.time_slot_map, i);
+ }
+ }
+ }
+}
+
+#define FIFO_RESET_TIMEOUT_CNT 1000
+#define FIFO_RESET_TIMEOUT_US 10
+static int xilinx_init_rx_dev_fifo(sdla_t *card, xilinx_softc_t *sc, unsigned char wait)
+{
+
+ u_int32_t reg;
+ u_int32_t dma_descr;
+ u_int8_t timeout=1;
+ u_int16_t i;
+
+ /* Clean RX DMA fifo */
+ dma_descr=(unsigned long)(sc->logic_ch_num<<4) + XILINX_RxDMA_DESCRIPTOR_HI;
+ reg=0;
+ bit_set((u_int8_t*)&reg, INIT_DMA_FIFO_CMD_BIT);
+
+#if defined(DEBUG_INIT)
+ log(LOG_DEBUG, "%s: Clearing RX Fifo DmaDescr=(0x%X) Reg=(0x%X) (%s)\n",
+ sc->if_name,
+ dma_descr,reg, __FUNCTION__);
+#endif
+
+ sdla_bus_write_4(card->hw,dma_descr,reg);
+
+ if (wait == WP_WAIT){
+ for(i=0;i<FIFO_RESET_TIMEOUT_CNT;i++){
+ sdla_bus_read_4(card->hw,dma_descr,&reg);
+ if (bit_test((u_int8_t*)&reg, INIT_DMA_FIFO_CMD_BIT)){
+ DELAY(FIFO_RESET_TIMEOUT_US);
+ continue;
+ }
+ timeout=0;
+ break;
+ }
+
+#if defined(DEBUG_INIT)
+ if (timeout){
+ log(LOG_INFO, "%s:%s: Error: Rx fifo reset timedout %u us\n",
+ card->devname,sc->if_name,i*FIFO_RESET_TIMEOUT_US);
+ }else{
+ log(LOG_INFO, "%s:%s: Rx Fifo reset successful %u us\n",
+ card->devname,sc->if_name,i*FIFO_RESET_TIMEOUT_US);
+ }
+#endif
+ }else{
+ timeout=0;
+ }
+
+ return timeout;
+}
+
+static int xilinx_init_tx_dev_fifo(sdla_t *card, xilinx_softc_t *sc, unsigned char wait)
+{
+ u_int32_t reg;
+ u_int32_t dma_descr;
+ u_int8_t timeout=1;
+ u_int16_t i;
+
+ /* Clean TX DMA fifo */
+ dma_descr=(unsigned long)(sc->logic_ch_num<<4) + XILINX_TxDMA_DESCRIPTOR_HI;
+ reg=0;
+ bit_set((u_int8_t*)&reg, INIT_DMA_FIFO_CMD_BIT);
+
+#if defined(DEBUG_INIT)
+ log(LOG_DEBUG, "%s: Clearing TX Fifo DmaDescr=(0x%X) Reg=(0x%X) (%s)\n",
+ sc->if_name,
+ dma_descr,reg, __FUNCTION__);
+#endif
+ sdla_bus_write_4(card->hw,dma_descr,reg);
+
+ if (wait == WP_WAIT){
+ for(i=0;i<FIFO_RESET_TIMEOUT_CNT;i++){
+ sdla_bus_read_4(card->hw,dma_descr,&reg);
+ if (bit_test((u_int8_t*)&reg, INIT_DMA_FIFO_CMD_BIT)){
+ DELAY(FIFO_RESET_TIMEOUT_US);
+ continue;
+ }
+ timeout=0;
+ break;
+ }
+
+#if defined(DEBUG_INIT)
+ if (timeout){
+ log(LOG_INFO, "%s:%s: Error: Tx fifo reset timedout %u us\n",
+ card->devname,sc->if_name,i*FIFO_RESET_TIMEOUT_US);
+ }else{
+ log(LOG_INFO, "%s:%s: Tx Fifo reset successful %u us\n",
+ card->devname,sc->if_name,i*FIFO_RESET_TIMEOUT_US);
+ }
+#endif
+ }else{
+ timeout=0;
+ }
+
+ return timeout;
+}
+
+
+static void xilinx_dev_enable(sdla_t *card, xilinx_softc_t *sc)
+{
+ u_int32_t reg;
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Enabling Global Inter Mask !\n",sc->if_name);
+#endif
+ /* Enable Logic Channel Interrupts for DMA and fifo */
+ sdla_bus_read_4(card->hw,
+ XILINX_GLOBAL_INTER_MASK, &reg);
+ bit_set((u_int8_t*)&reg, sc->logic_ch_num);
+
+ sdla_bus_write_4(card->hw,
+ XILINX_GLOBAL_INTER_MASK, reg);
+
+ bit_set((u_int8_t*)&card->u.xilinx.active_ch_map, sc->logic_ch_num);
+}
+
+static void xilinx_dev_close(sdla_t *card, xilinx_softc_t *sc)
+{
+ u_int32_t reg;
+ unsigned long dma_descr;
+ int s;
+
+#if defined(DEBUG_INIT)
+ log(LOG_DEBUG, "-- Close Xilinx device. --\n");
+#endif
+ /* Disable Logic Channel Interrupts for DMA and fifo */
+ sdla_bus_read_4(card->hw, XILINX_GLOBAL_INTER_MASK, &reg);
+
+ bit_clear((u_int8_t*)&reg, sc->logic_ch_num);
+ bit_clear((u_int8_t*)&card->u.xilinx.active_ch_map, sc->logic_ch_num);
+
+ /* We are masking the sc interrupt.
+ * Lock to make sure that the interrupt is
+ * not running */
+ s = splnet();
+ sdla_bus_write_4(card->hw, XILINX_GLOBAL_INTER_MASK, reg);
+ splx(s);
+
+ reg=0;
+
+ /* Select an HDLC logic channel for configuration */
+ sdla_bus_read_4(card->hw, XILINX_TIMESLOT_HDLC_CHAN_REG, &reg);
+
+ reg&=~HDLC_LOGIC_CH_BIT_MASK;
+ reg&= HDLC_LCH_TIMESLOT_MASK; /* mask not valid bits */
+
+ sdla_bus_write_4(card->hw,
+ XILINX_TIMESLOT_HDLC_CHAN_REG,
+ (reg|(sc->logic_ch_num&HDLC_LOGIC_CH_BIT_MASK)));
+
+
+ reg=0;
+ xilinx_write_ctrl_hdlc(card,
+ sc->first_time_slot,
+ XILINX_HDLC_CONTROL_REG,
+ reg);
+
+ /* Clear descriptors */
+ reg=0;
+ dma_descr=(sc->logic_ch_num<<4) + XILINX_RxDMA_DESCRIPTOR_HI;
+ sdla_bus_write_4(card->hw,dma_descr,reg);
+ dma_descr=(sc->logic_ch_num<<4) + XILINX_TxDMA_DESCRIPTOR_HI;
+ sdla_bus_write_4(card->hw,dma_descr,reg);
+
+ /* FIXME: Cleanp up Tx and Rx buffers */
+}
+
+static int xilinx_dma_rx(sdla_t *card, xilinx_softc_t *sc)
+{
+ u_int32_t reg;
+ unsigned long dma_descr;
+ unsigned long bus_addr;
+ wp_rx_element_t *rx_el;
+
+ /* sanity check: make sure that DMA is in ready state */
+#if 0
+ dma_descr=(sc->logic_ch_num<<4) + XILINX_RxDMA_DESCRIPTOR_HI;
+ sdla_bus_read_4(card->hw,dma_descr, &reg);
+
+ if (bit_test((u_int8_t*)&reg,RxDMA_HI_DMA_GO_READY_BIT)){
+ log(LOG_INFO, "%s: Error: RxDMA GO Ready bit set on dma Rx\n",
+ card->devname);
+ return -EFAULT;
+ }
+#endif
+
+ if (sc->rx_dma_mbuf){
+ log(LOG_INFO, "%s: Critial Error: Rx Dma Buf busy!\n",
+ sc->if_name);
+ return -EINVAL;
+ }
+
+ IF_DEQUEUE(&sc->wp_rx_free_list, sc->rx_dma_mbuf);
+
+ if (!sc->rx_dma_mbuf){
+ log(LOG_INFO, "%s: Critical Error no rx dma buf Free=%d Comp=%d!\n",
+ sc->if_name,
+ sc->wp_rx_free_list.ifq_len,
+ sc->wp_rx_complete_list.ifq_len);
+
+ return -ENOMEM;
+ }
+
+ rx_el = mtod(sc->rx_dma_mbuf, wp_rx_element_t*);
+ sc->rx_dma_mbuf->m_len = sizeof(wp_rx_element_t);
+ sc->rx_dma_mbuf->m_pkthdr.len = sc->rx_dma_mbuf->m_len;
+ memset(rx_el,0,sizeof(wp_rx_element_t));
+
+ bus_addr = kvtop(mtod(sc->rx_dma_mbuf, caddr_t) + sc->rx_dma_mbuf->m_len);
+
+ if (!bus_addr){
+ log(LOG_INFO, "%s: %s Critical error pci_map_single() failed!\n",
+ sc->if_name,__FUNCTION__);
+ return -EINVAL;
+ }
+
+ rx_el->dma_addr=bus_addr;
+
+ /* Write the pointer of the data packet to the
+ * DMA address register */
+ reg=bus_addr;
+
+ /* Set the 32bit alignment of the data length.
+ * Since we are setting up for rx, set this value
+ * to Zero */
+ reg&=~(RxDMA_LO_ALIGNMENT_BIT_MASK);
+
+ dma_descr=(sc->logic_ch_num<<4) + XILINX_RxDMA_DESCRIPTOR_LO;
+
+#if defined(DEBUG_RX)
+ log(LOG_INFO,"%s: RxDMA_LO = 0x%X, BusAddr=0x%lX DmaDescr=0x%lX (%s)\n",
+ card->devname,reg,bus_addr,dma_descr, __FUNCTION__);
+#endif
+ sdla_bus_write_4(card->hw,dma_descr,reg);
+
+ dma_descr=(unsigned long)(sc->logic_ch_num<<4) + XILINX_RxDMA_DESCRIPTOR_HI;
+
+ reg =0;
+
+ reg|=(sc->dma_mtu>>2)&RxDMA_HI_DMA_DATA_LENGTH_MASK;
+
+#ifdef TRUE_FIFO_SIZE
+ reg|=(sc->fifo_size_code&DMA_FIFO_SIZE_MASK)<<DMA_FIFO_SIZE_SHIFT;
+#else
+
+ reg|=(HARD_FIFO_CODE&DMA_FIFO_SIZE_MASK)<<DMA_FIFO_SIZE_SHIFT;
+#endif
+ reg|=(sc->fifo_base_addr&DMA_FIFO_BASE_ADDR_MASK)<<
+ DMA_FIFO_BASE_ADDR_SHIFT;
+
+ bit_set((u_int8_t*)&reg, RxDMA_HI_DMA_GO_READY_BIT);
+
+#if defined(DEBUG_RX)
+ log(LOG_INFO, "%s: RXDMA_HI = 0x%X, BusAddr=0x%lX DmaDescr=0x%lX (%s)\n",
+ sc->if_name, reg,bus_addr,dma_descr, __FUNCTION__);
+#endif
+
+ sdla_bus_write_4(card->hw,dma_descr,reg);
+
+ bit_set((u_int8_t*)&sc->rx_dma, 0);
+
+ return 0;
+}
+
+
+static int xilinx_dma_tx (sdla_t *card, xilinx_softc_t *sc)
+{
+ u_int32_t reg=0;
+ struct mbuf *m;
+ unsigned long dma_descr;
+ unsigned char len_align=0;
+ int len=0;
+
+#if defined(DEBUG_TX)
+ log(LOG_INFO, "------ Setup Tx DMA descriptor. --\n");
+#endif
+
+ if (bit_test((u_int8_t*)&sc->dma_status, TX_BUSY)){
+ log(LOG_INFO, "%s: TX_BUSY set (%s:%d)!\n",
+ sc->if_name, __FUNCTION__,__LINE__);
+ return -EBUSY;
+ }
+ bit_set((u_int8_t*)&sc->dma_status, TX_BUSY);
+
+
+ /* Free the previously skb dma mapping.
+ * In this case the tx interrupt didn't finish
+ * and we must re-transmit.*/
+
+ if (sc->tx_dma_addr && sc->tx_dma_len){
+ log(LOG_INFO, "%s: Unmaping tx_dma_addr in %s\n",
+ sc->if_name,__FUNCTION__);
+
+ sc->tx_dma_addr=0;
+ sc->tx_dma_len=0;
+ }
+
+ /* Free the previously sent tx packet. To
+ * minimize tx isr, the previously transmitted
+ * packet is deallocated here */
+ if (sc->tx_dma_mbuf){
+ log(LOG_INFO, "%s: Deallocating tx_dma_mbuf in %s\n",
+ sc->if_name,__FUNCTION__);
+ m_freem(sc->tx_dma_mbuf);
+ sc->tx_dma_mbuf=NULL;
+ }
+
+
+ /* check queue pointers befor start transmittion */
+
+ /* sanity check: make sure that DMA is in ready state */
+ dma_descr=(sc->logic_ch_num<<4) + XILINX_TxDMA_DESCRIPTOR_HI;
+
+#if defined(DEBUG_TX)
+ log(LOG_INFO, "%s: sc logic ch=%ld dma_descr=0x%lx set (%s:%d)!\n",
+ sc->if_name, sc->logic_ch_num,dma_descr,
+ __FUNCTION__,__LINE__);
+#endif
+
+ sdla_bus_read_4(card->hw,dma_descr, &reg);
+
+ if (bit_test((u_int8_t*)&reg, TxDMA_HI_DMA_GO_READY_BIT)){
+ log(LOG_INFO, "%s: Error: TxDMA GO Ready bit set on dma Tx 0x%X\n",
+ card->devname,reg);
+ bit_clear((u_int8_t*)&sc->dma_status, TX_BUSY);
+ return -EFAULT;
+ }
+
+ IF_DEQUEUE(&sc->wp_tx_pending_list, m);
+
+ if (!m){
+ bit_clear((u_int8_t*)&sc->dma_status, TX_BUSY);
+ return -ENOBUFS;
+ }else{
+
+ len = m->m_len;
+ if (len > MAX_XILINX_TX_DMA_SIZE){
+ /* FIXME: We need to split this frame into
+ * multiple parts. For now thought
+ * just drop it :) */
+ log(LOG_INFO, "%s: Tx len %d > %d (MAX TX DMA LEN) (%s:%d)!\n",
+ sc->if_name, len, MAX_XILINX_TX_DMA_SIZE,
+ __FUNCTION__,__LINE__);
+ m_freem(m);
+ bit_clear((u_int8_t*)&sc->dma_status, TX_BUSY);
+ return -EINVAL;
+ }
+
+ sc->tx_dma_addr = kvtop(mtod(m, caddr_t));
+ sc->tx_dma_len = len;
+ }
+
+ if (sc->tx_dma_addr & 0x03){
+ log(LOG_INFO, "%s: Error: Tx Ptr not aligned to 32bit boudary!\n",
+ card->devname);
+
+ if (m){
+ m_freem(m);
+ }
+
+ bit_clear((u_int8_t*)&sc->dma_status, TX_BUSY);
+ return -EINVAL;
+ }
+
+ sc->tx_dma_mbuf=m;
+
+ /* WARNING: Do ont use the "skb" pointer from
+ * here on. The skb pointer might not exist if
+ * we are in transparent mode */
+
+ dma_descr=(sc->logic_ch_num<<4) + XILINX_TxDMA_DESCRIPTOR_LO;
+
+ /* Write the pointer of the data packet to the
+ * DMA address register */
+ reg=sc->tx_dma_addr;
+
+ /* Set the 32bit alignment of the data length.
+ * Used to pad the tx packet to the 32 bit
+ * boundary */
+ reg&=~(TxDMA_LO_ALIGNMENT_BIT_MASK);
+ reg|=(len&0x03);
+
+ if (len&0x03){
+ len_align=1;
+ }
+
+#if defined(DEBUG_TX)
+ log(LOG_INFO, "%s: TXDMA_LO=0x%X PhyAddr=0x%lX DmaDescr=0x%lX (%s)\n",
+ sc->if_name, reg,sc->tx_dma_addr,dma_descr, __FUNCTION__);
+#endif
+
+ sdla_bus_write_4(card->hw,dma_descr,reg);
+
+ dma_descr=(sc->logic_ch_num<<4) + XILINX_TxDMA_DESCRIPTOR_HI;
+
+ reg=0;
+ reg|=(((len>>2)+len_align)&TxDMA_HI_DMA_DATA_LENGTH_MASK);
+
+#ifdef TRUE_FIFO_SIZE
+ reg|=(sc->fifo_size_code&DMA_FIFO_SIZE_MASK)<<DMA_FIFO_SIZE_SHIFT;
+#else
+
+ reg|=(HARD_FIFO_CODE&DMA_FIFO_SIZE_MASK)<<DMA_FIFO_SIZE_SHIFT;
+#endif
+ reg|=(sc->fifo_base_addr&DMA_FIFO_BASE_ADDR_MASK)<<
+ DMA_FIFO_BASE_ADDR_SHIFT;
+
+ /* Only enable the Frame Start/Stop on
+ * non-transparent hdlc configuration */
+
+ bit_set((u_int8_t*)&reg, TxDMA_HI_DMA_FRAME_START_BIT);
+ bit_set((u_int8_t*)&reg, TxDMA_HI_DMA_FRAME_END_BIT);
+
+ bit_set((u_int8_t*)&reg, TxDMA_HI_DMA_GO_READY_BIT);
+
+#if defined(DEBUG_TX)
+ log(LOG_INFO, "%s: TXDMA_HI=0x%X DmaDescr=0x%lX (%s)\n",
+ sc->if_name, reg,dma_descr, __FUNCTION__);
+#endif
+
+ sdla_bus_write_4(card->hw,dma_descr,reg);
+
+ return 0;
+
+}
+
+static void xilinx_dma_tx_complete (sdla_t *card, xilinx_softc_t *sc)
+{
+ u_int32_t reg=0;
+ unsigned long dma_descr;
+
+#if defined(DEBUG_TX)
+ log(LOG_INFO, "%s: TX DMA complete\n", card->devname);
+#endif
+ /* DEBUGTX */
+/* sdla_bus_read_4(card->hw,0x78, &tmp1); */
+
+ dma_descr=(sc->logic_ch_num<<4) + XILINX_TxDMA_DESCRIPTOR_HI;
+ sdla_bus_read_4(card->hw,dma_descr, &reg);
+
+ if (!sc->tx_dma_mbuf){
+
+ log(LOG_INFO, "%s: Critical Error: Tx DMA intr: no tx mbuf !\n",
+ card->devname);
+ bit_clear((u_int8_t*)&sc->dma_status, TX_BUSY);
+ return;
+
+ }else{
+ sc->tx_dma_addr=0;
+ sc->tx_dma_len=0;
+
+
+ /* Do not free the packet here,
+ * copy the packet dma info into csum
+ * field and let the bh handler analyze
+ * the transmitted packet.
+ */
+
+ if (reg & TxDMA_HI_DMA_PCI_ERROR_RETRY_TOUT){
+
+ log(LOG_INFO, "%s:%s: PCI Error: 'Retry' exceeds maximum (64k): Reg=0x%X!\n",
+ card->devname,sc->if_name,reg);
+
+ if (++sc->pci_retry < 3){
+ bit_set((u_int8_t*)&reg, TxDMA_HI_DMA_GO_READY_BIT);
+
+ log(LOG_INFO, "%s: Retry: TXDMA_HI=0x%X DmaDescr=0x%lX (%s)\n",
+ sc->if_name, reg,dma_descr, __FUNCTION__);
+
+ sdla_bus_write_4(card->hw,dma_descr,reg);
+ return;
+ }
+ }
+
+ sc->pci_retry=0;
+ sc->tx_dma_mbuf->m_pkthdr.csum = reg;
+ IF_ENQUEUE(&sc->wp_tx_complete_list, sc->tx_dma_mbuf);
+ sc->tx_dma_mbuf=NULL;
+
+ bit_clear((u_int8_t*)&sc->dma_status, TX_BUSY);
+
+ xilinx_process_packet(sc);
+ }
+
+}
+
+
+static void xilinx_tx_post_complete (sdla_t *card, xilinx_softc_t *sc, struct mbuf *m)
+{
+ struct ifnet *ifp;
+ unsigned long reg = m->m_pkthdr.csum;
+
+ WAN_ASSERT1(sc == NULL);
+ ifp = (struct ifnet*)&sc->common.ifp;
+ if ((bit_test((u_int8_t*)&reg, TxDMA_HI_DMA_GO_READY_BIT)) ||
+ (reg & TxDMA_HI_DMA_DATA_LENGTH_MASK) ||
+ (reg & TxDMA_HI_DMA_PCI_ERROR_MASK)){
+
+#if defined(DEBUG_TX)
+ log(LOG_INFO, "%s:%s: Tx DMA Descriptor=0x%lX\n",
+ card->devname,sc->if_name,reg);
+#endif
+
+ /* Checking Tx DMA Go bit. Has to be '0' */
+ if (bit_test((u_int8_t*)&reg, TxDMA_HI_DMA_GO_READY_BIT)){
+ log(LOG_INFO, "%s:%s: Error: TxDMA Intr: GO bit set on Tx intr\n",
+ card->devname,sc->if_name);
+ }
+
+ if (reg & TxDMA_HI_DMA_DATA_LENGTH_MASK){
+ log(LOG_INFO, "%s:%s: Error: TxDMA Length not equal 0 \n",
+ card->devname,sc->if_name);
+ }
+
+ /* Checking Tx DMA PCI error status. Has to be '0's */
+ if (reg&TxDMA_HI_DMA_PCI_ERROR_MASK){
+
+ if (reg & TxDMA_HI_DMA_PCI_ERROR_M_ABRT){
+ log(LOG_INFO, "%s:%s: Tx Error: Abort from Master: pci fatal error!\n",
+ card->devname,sc->if_name);
+ }
+ if (reg & TxDMA_HI_DMA_PCI_ERROR_T_ABRT){
+ log(LOG_INFO, "%s:%s: Tx Error: Abort from Target: pci fatal error!\n",
+ card->devname,sc->if_name);
+ }
+ if (reg & TxDMA_HI_DMA_PCI_ERROR_DS_TOUT){
+ log(LOG_INFO, "%s:%s: Tx Warning: PCI Latency Timeout!\n",
+ card->devname,sc->if_name);
+ goto tx_post_ok;
+ }
+ if (reg & TxDMA_HI_DMA_PCI_ERROR_RETRY_TOUT){
+ log(LOG_INFO, "%s:%s: Tx Error: 'Retry' exceeds maximum (64k): pci fatal error!\n",
+ card->devname,sc->if_name);
+ }
+ }
+ goto tx_post_exit;
+ }
+
+tx_post_ok:
+
+ if (ifp){
+ ifp->if_opackets++;
+ ifp->if_obytes += m->m_len;
+ }
+
+ /* Indicate that the first tx frame went
+ * out on the transparent link */
+ bit_set((u_int8_t*)&sc->idle_start, 0);
+
+tx_post_exit:
+
+ if (!xilinx_dma_tx(card,sc)){
+ /* If we was able to transmit and the interface is set to OACTIVE
+ ** remove this flag and let kernel try to transmit. */
+ if (ifp->if_flags & IFF_OACTIVE){
+ ifp->if_flags &= ~IFF_OACTIVE;
+ }
+ }
+ return;
+}
+
+static void xilinx_dma_rx_complete (sdla_t *card, xilinx_softc_t *sc)
+{
+ unsigned long dma_descr;
+ struct mbuf *m;
+ wp_rx_element_t *rx_el;
+
+ bit_clear((u_int8_t*)&sc->rx_dma, 0);
+
+ if (!sc->rx_dma_mbuf){
+ log(LOG_INFO, "%s: Critical Error: rx_dma_mbuf\n",sc->if_name);
+ return;
+ }
+
+ rx_el= mtod(sc->rx_dma_mbuf, wp_rx_element_t *);
+
+ /* Reading Rx DMA descriptor information */
+ dma_descr=(sc->logic_ch_num<<4) + XILINX_RxDMA_DESCRIPTOR_LO;
+ sdla_bus_read_4(card->hw,dma_descr, &rx_el->align);
+ rx_el->align&=RxDMA_LO_ALIGNMENT_BIT_MASK;
+
+ dma_descr=(sc->logic_ch_num<<4) + XILINX_RxDMA_DESCRIPTOR_HI;
+ sdla_bus_read_4(card->hw,dma_descr, &rx_el->reg);
+
+ rx_el->pkt_error = sc->pkt_error;
+ sc->pkt_error=0;
+
+#if defined(DEBUG_RX)
+ log(LOG_INFO, "%s: RX HI=0x%X LO=0x%X DMA=0x%lX (%s:%d)\n",
+ sc->if_name,rx_el->reg,rx_el->align,rx_el->dma_addr,
+ __FUNCTION__,__LINE__);
+#endif
+
+ m=sc->rx_dma_mbuf;
+ sc->rx_dma_mbuf=NULL;
+
+ xilinx_dma_rx(card,sc);
+
+ IF_ENQUEUE(&sc->wp_rx_complete_list, m);
+
+ xilinx_process_packet(sc);
+
+/* sdla_bus_read_4(card->hw,0x80, &rx_empty); */
+}
+
+
+static void xilinx_rx_post_complete (sdla_t *card, xilinx_softc_t *sc,
+ struct mbuf *m,
+ struct mbuf **new_m,
+ unsigned char *pkt_error)
+{
+ struct ifnet *ifp;
+ unsigned int len,data_error = 0;
+ wp_rx_element_t *rx_el = mtod(m, wp_rx_element_t *);
+
+ WAN_ASSERT1(sc == NULL);
+ ifp = (struct ifnet*)&sc->common.ifp; /*m->m_pkthdr.rcvif;*/
+
+#if defined(DEBUG_RX)
+ log(LOG_INFO, "%s: RX HI=0x%X LO=0x%X DMA=0x%lX (%s:%d)\n",
+ sc->if_name,
+ rx_el->reg,
+ rx_el->align,
+ rx_el->dma_addr,
+ __FUNCTION__,__LINE__);
+#endif
+ rx_el->align&=RxDMA_LO_ALIGNMENT_BIT_MASK;
+ *pkt_error=0;
+ *new_m=NULL;
+
+
+ /* Checking Rx DMA Go bit. Has to be '0' */
+ if (bit_test((u_int8_t*)&rx_el->reg, RxDMA_HI_DMA_GO_READY_BIT)){
+ log(LOG_INFO, "%s: Error: RxDMA Intr: GO bit set on Rx intr\n",
+ card->devname);
+ ifp->if_ierrors++;
+ goto rx_comp_error;
+ }
+
+ /* Checking Rx DMA PCI error status. Has to be '0's */
+ if (rx_el->reg&RxDMA_HI_DMA_PCI_ERROR_MASK){
+
+ if (rx_el->reg & RxDMA_HI_DMA_PCI_ERROR_M_ABRT){
+#if defined(DEBUG_ERR)
+ log(LOG_INFO, "%s: Rx Error: Abort from Master: pci fatal error!\n",
+ card->devname);
+#endif
+ }
+ if (rx_el->reg & RxDMA_HI_DMA_PCI_ERROR_T_ABRT){
+#if defined(DEBUG_ERR)
+ log(LOG_INFO, "%s: Rx Error: Abort from Target: pci fatal error!\n",
+ card->devname);
+#endif
+ }
+ if (rx_el->reg & RxDMA_HI_DMA_PCI_ERROR_DS_TOUT){
+#if defined(DEBUG_ERR)
+ log(LOG_INFO, "%s: Rx Error: No 'DeviceSelect' from target: pci fatal error!\n",
+ card->devname);
+#endif
+ }
+ if (rx_el->reg & RxDMA_HI_DMA_PCI_ERROR_RETRY_TOUT){
+#if defined(DEBUG_ERR)
+ log(LOG_INFO, "%s: Rx Error: 'Retry' exceeds maximum (64k): pci fatal error!\n",
+ card->devname);
+#endif
+ }
+#if defined(DEBUG_ERR)
+ log(LOG_INFO, "%s: RXDMA PCI ERROR = 0x%x\n",
+ card->devname,rx_el->reg);
+#endif
+ if (ifp) ifp->if_ierrors++;
+ goto rx_comp_error;
+ }
+
+ /* Checking Rx DMA Frame start bit. (information for api) */
+ if (!bit_test((u_int8_t*)&rx_el->reg, RxDMA_HI_DMA_FRAME_START_BIT)){
+#if defined(DEBUG_ERR)
+ log(LOG_INFO, "%s: RxDMA Intr: Start flag missing: MTU Mismatch! Reg=0x%X\n",
+ card->devname,rx_el->reg);
+#endif
+ if (ifp) ifp->if_ierrors++;
+ goto rx_comp_error;
+ }
+
+ /* Checking Rx DMA Frame end bit. (information for api) */
+ if (!bit_test((u_int8_t*)&rx_el->reg, RxDMA_HI_DMA_FRAME_END_BIT)){
+#if defined(DEBUG_ERR)
+ log(LOG_INFO, "%s: RxDMA Intr: End flag missing: MTU Mismatch! Reg=0x%X\n",
+ card->devname,rx_el->reg);
+#endif
+ if (ifp) ifp->if_ierrors++;
+ goto rx_comp_error;
+
+ } else { /* Check CRC error flag only if this is the end of Frame */
+
+ if (bit_test((u_int8_t*)&rx_el->reg, RxDMA_HI_DMA_CRC_ERROR_BIT)){
+#if defined(DEBUG_ERR)
+ log(LOG_INFO, "%s: RxDMA Intr: CRC Error! Reg=0x%X\n",
+ card->devname,rx_el->reg);
+#endif
+ if (ifp) ifp->if_ierrors++;
+ bit_set((u_int8_t*)&rx_el->pkt_error, WP_CRC_ERROR_BIT);
+ data_error = 1;
+ }
+
+ /* Check if this frame is an abort, if it is
+ * drop it and continue receiving */
+ if (bit_test((u_int8_t*)&rx_el->reg, RxDMA_HI_DMA_FRAME_ABORT_BIT)){
+#if defined(DEBUG_ERR)
+ log(LOG_INFO, "%s: RxDMA Intr: Abort! Reg=0x%X\n",
+ card->devname,rx_el->reg);
+#endif
+ if (ifp) ifp->if_ierrors++;
+ bit_set((u_int8_t*)&rx_el->pkt_error, WP_ABORT_ERROR_BIT);
+ data_error = 1;
+ }
+
+ if (data_error){
+ goto rx_comp_error;
+ }
+ }
+
+ len=rx_el->reg&RxDMA_HI_DMA_DATA_LENGTH_MASK;
+
+ /* In HDLC mode, calculate rx length based
+ * on alignment value, received from DMA */
+ len=(((sc->dma_mtu>>2)-len)<<2) - (~(rx_el->align)&RxDMA_LO_ALIGNMENT_BIT_MASK);
+
+ *pkt_error=rx_el->pkt_error;
+
+ /* After a RX FIFO overflow, we must mark max 7
+ * subsequent frames since firmware, cannot
+ * guarantee the contents of the fifo */
+
+ if (bit_test((u_int8_t*)&rx_el->pkt_error, WP_FIFO_ERROR_BIT)){
+ if (++sc->rx_fifo_err_cnt >= WP_MAX_FIFO_FRAMES){
+ sc->rx_fifo_err_cnt=0;
+ }
+ bit_set((u_int8_t*)pkt_error, WP_FIFO_ERROR_BIT);
+ }else{
+ if (sc->rx_fifo_err_cnt){
+ if (++sc->rx_fifo_err_cnt >= WP_MAX_FIFO_FRAMES){
+ sc->rx_fifo_err_cnt=0;
+ }
+ bit_set((u_int8_t*)pkt_error, WP_FIFO_ERROR_BIT);
+ }
+ }
+
+ if (len > aft_rx_copyback){
+ /* The rx size is big enough, thus
+ * send this buffer up the stack
+ * and allocate another one */
+#if 0
+ memset(&skb->cb[0],0,sizeof(wp_rx_element_t));
+#endif
+ memset(mtod(m, caddr_t),0,sizeof(wp_rx_element_t));
+ m_adj(m, sizeof(wp_rx_element_t));
+ m->m_len += len;
+ m->m_pkthdr.len = m->m_len;
+ *new_m=m;
+
+ aft_alloc_rx_dma_buff(card,sc,1);
+ }else{
+ struct mbuf *m0;
+ /* The rx packet is very
+ * small thus, allocate a new
+ * buffer and pass it up */
+ m0 = wan_mbuf_alloc();
+ if (m0 == NULL){
+ log(LOG_INFO, "%s: Failed to allocate mbuf!\n",
+ sc->if_name);
+ if (ifp) ifp->if_ierrors++;
+ goto rx_comp_error;
+ }
+
+ m0->m_len = m0->m_pkthdr.len = len;
+ memcpy(mtod(m0, caddr_t), mtod(m, caddr_t) + m->m_len, len);
+ *new_m = m0;
+ aft_init_requeue_free_m(sc, m);
+ }
+
+ return;
+
+rx_comp_error:
+
+ aft_init_requeue_free_m(sc, m);
+ return;
+}
+
+
+static char request_xilinx_logical_channel_num (sdla_t *card, xilinx_softc_t *sc, long *free_ch)
+{
+ char logic_ch=-1, free_logic_ch=-1;
+ int i,err;
+
+ *free_ch=-1;
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "-- Request_Xilinx_logic_channel_num:--\n");
+ log(LOG_INFO, "%s: Global Num Timeslots=%d Global Logic ch Map 0x%lX (%s:%d)\n",
+ sc->if_name,
+ card->u.xilinx.num_of_time_slots,
+ card->u.xilinx.logic_ch_map,
+ __FUNCTION__,__LINE__);
+#endif
+
+ err=request_fifo_baddr_and_size(card,sc);
+ if (err){
+ return -1;
+ }
+
+
+ for (i=0;i<card->u.xilinx.num_of_time_slots;i++){
+ if (!bit_test((u_int8_t*)&card->u.xilinx.logic_ch_map, i)){
+ bit_set((u_int8_t*)&card->u.xilinx.logic_ch_map, i);
+ logic_ch=i;
+ break;
+ }
+ }
+
+ if (logic_ch == -1){
+ return logic_ch;
+ }
+
+ for (i=0;i<card->u.xilinx.num_of_time_slots;i++){
+ if (!bit_test((u_int8_t*)&card->u.xilinx.logic_ch_map, i)){
+ free_logic_ch=HDLC_FREE_LOGIC_CH;
+ break;
+ }
+ }
+
+ if (card->u.xilinx.dev_to_ch_map[(unsigned char)logic_ch]){
+ log(LOG_INFO, "%s: Error, request logical ch=%d map busy\n",
+ card->devname,logic_ch);
+ return -1;
+ }
+
+ *free_ch=free_logic_ch;
+
+ card->u.xilinx.dev_to_ch_map[(unsigned char)logic_ch]=(void*)sc;
+
+ if (logic_ch > card->u.xilinx.top_logic_ch){
+ card->u.xilinx.top_logic_ch=logic_ch;
+ xilinx_dma_max_logic_ch(card);
+ }
+
+
+ return logic_ch;
+}
+
+static void free_xilinx_logical_channel_num (sdla_t *card, int logic_ch)
+{
+ bit_clear ((u_int8_t*)&card->u.xilinx.logic_ch_map, logic_ch);
+ card->u.xilinx.dev_to_ch_map[logic_ch]=NULL;
+
+ if (logic_ch >= card->u.xilinx.top_logic_ch){
+ int i;
+
+ card->u.xilinx.top_logic_ch=XILINX_DEFLT_ACTIVE_CH;
+
+ for (i=0;i<card->u.xilinx.num_of_time_slots;i++){
+ if (card->u.xilinx.dev_to_ch_map[logic_ch]){
+ card->u.xilinx.top_logic_ch=i;
+ }
+ }
+
+ xilinx_dma_max_logic_ch(card);
+ }
+
+}
+
+static void xilinx_dma_max_logic_ch(sdla_t *card)
+{
+ u_int32_t reg;
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "-- Xilinx_dma_max_logic_ch :--\n");
+#endif
+
+ sdla_bus_read_4(card->hw,XILINX_DMA_CONTROL_REG, &reg);
+
+ /* Set up the current highest active logic channel */
+
+ reg&=DMA_ACTIVE_CHANNEL_BIT_MASK;
+ reg|=(card->u.xilinx.top_logic_ch << DMA_ACTIVE_CHANNEL_BIT_SHIFT);
+
+ sdla_bus_write_4(card->hw,XILINX_DMA_CONTROL_REG,reg);
+}
+
+static int aft_init_requeue_free_m(xilinx_softc_t *sc, struct mbuf *m)
+{
+ int err;
+
+ m->m_data = (m->m_flags & M_EXT) ? m->m_ext.ext_buf : m->m_pktdat;
+ m->m_pkthdr.len = m->m_len = 0;
+
+ memset(mtod(m, caddr_t),0,sizeof(wp_rx_element_t));
+ IF_ENQUEUE(&sc->wp_rx_free_list, m);
+ return err;
+}
+
+static int aft_alloc_rx_dma_buff(sdla_t *card, xilinx_softc_t *sc, int num)
+{
+ int i;
+ struct mbuf *m;
+
+ for (i=0;i<num;i++){
+ m = wan_mbuf_alloc();
+ if (m == NULL){
+ log(LOG_INFO, "%s: %s no memory\n",
+ sc->if_name,__FUNCTION__);
+ return -ENOMEM;
+ }
+ IF_ENQUEUE(&sc->wp_rx_free_list, m);
+ }
+
+ return 0;
+}
+
+
+
+
+/*============================================================================
+ * Enable timer interrupt
+ */
+static void enable_timer (void* card_id)
+{
+ sdla_t *card = (sdla_t*)card_id;
+ int s;
+
+ s = splnet();
+ sdla_te_polling(card);
+ splx(s);
+ return;
+}
+
+static void xilinx_process_packet(xilinx_softc_t *sc)
+{
+ struct ifnet *ifp;
+ struct mbuf *new_m, *m;
+ unsigned char pkt_error;
+
+ WAN_ASSERT1(sc == NULL);
+ for(;;){
+ IF_DEQUEUE(&sc->wp_rx_complete_list, m);
+ if (m == NULL)
+ break;
+
+ new_m=NULL;
+ pkt_error=0;
+
+ /* The post function will take care
+ * of the skb and new_skb buffer.
+ * If new_skb buffer exists, driver
+ * must pass it up the stack, or free it */
+ xilinx_rx_post_complete (sc->common.card, sc,
+ m,
+ &new_m,
+ &pkt_error);
+ if (new_m){
+
+ ifp = (struct ifnet*)&sc->common.ifp;
+#if defined(DEBUG_RX)
+ log(LOG_INFO, "%s: Receiving packet %d bytes!\n",
+ ifp->if_xname, new_m->m_len);
+#endif
+ wanpipe_generic_input(ifp, new_m);
+ }
+ }
+
+ for(;;){
+ IF_DEQUEUE(&sc->wp_tx_complete_list, m);
+ if (m == NULL)
+ break;
+ xilinx_tx_post_complete (sc->common.card,sc,m);
+ m_freem(m);
+ }
+
+ return;
+}
+
+static int fifo_error_interrupt(sdla_t *card, unsigned long reg)
+{
+ u_int32_t rx_status, tx_status;
+ u_int32_t err=0;
+ u_int32_t i;
+ xilinx_softc_t *sc;
+
+#if defined(DEBUG_ERR)
+ log(LOG_INFO, "%s: Fifo error interrupt!\n",
+ card->devname);
+#endif
+
+ /* Clear HDLC pending registers */
+ sdla_bus_read_4(card->hw,XILINX_HDLC_TX_INTR_PENDING_REG,&tx_status);
+ sdla_bus_read_4(card->hw,XILINX_HDLC_RX_INTR_PENDING_REG,&rx_status);
+
+ if (card->state != WAN_CONNECTED){
+ log(LOG_INFO, "%s: Warning: Ignoring Error Intr: link disc!\n",
+ card->devname);
+ return 0;
+ }
+
+ tx_status&=card->u.xilinx.active_ch_map;
+ rx_status&=card->u.xilinx.active_ch_map;
+
+ if (tx_status != 0){
+ for (i=0;i<card->u.xilinx.num_of_time_slots;i++){
+ if (bit_test((u_int8_t*)&tx_status, i) && bit_test((u_int8_t*)&card->u.xilinx.logic_ch_map, i)){
+ struct ifnet *ifp;
+
+ sc=(xilinx_softc_t*)card->u.xilinx.dev_to_ch_map[i];
+ if (!sc){
+ log(LOG_INFO, "Warning: ignoring tx error intr: no dev!\n");
+ continue;
+ }
+
+ ifp = (struct ifnet*)&sc->common.ifp;
+#if 0
+ if (!(ifp->if_flags & IFF_UP)){
+ log(LOG_INFO, "%s: Warning: ignoring tx error intr: dev down 0x%X UP=0x%X!\n",
+ ifp->if_xname,
+ sc->common.state,
+ sc->ignore_modem);
+ continue;
+ }
+#endif
+
+ if (card->state != WAN_CONNECTED){
+ log(LOG_INFO, "%s: Warning: ignoring tx error intr: dev disc!\n",
+ ifp->if_xname);
+ continue;
+ }
+
+#if defined(DEBUG_ERR)
+ log(LOG_INFO, "%s:%s: Warning TX Fifo Error on LogicCh=%ld Slot=%d!\n",
+ card->devname,sc->if_name,sc->logic_ch_num,i);
+#endif
+ xilinx_tx_fifo_under_recover(card,sc);
+ err=-EINVAL;
+ }
+ }
+ }
+
+
+ if (rx_status != 0){
+ for (i=0;i<card->u.xilinx.num_of_time_slots;i++){
+ if (bit_test((u_int8_t*)&rx_status, i) && bit_test((u_int8_t*)&card->u.xilinx.logic_ch_map, i)){
+ struct ifnet *ifp;
+ sc=(xilinx_softc_t*)card->u.xilinx.dev_to_ch_map[i];
+ if (!sc){
+ continue;
+ }
+
+ ifp = (struct ifnet*)&sc->common.ifp;
+#if 0
+ if (!(ifp->if_flags & IFF_UP)){
+ log(LOG_INFO, "%s: Warning: ignoring rx error intr: dev down 0x%X UP=0x%X!\n",
+ ifp->if_xname,
+ sc->common.state,
+ sc->ignore_modem);
+ continue;
+ }
+#endif
+
+ if (card->state != WAN_CONNECTED){
+ log(LOG_INFO, "%s: Warning: ignoring rx error intr: dev disc!\n",
+ ifp->if_xname);
+ continue;
+ }
+
+#if defined(DEBUG_ERR)
+ log(LOG_INFO, "%s:%s: Warning RX Fifo Error on LCh=%ld Slot=%d RxCL=%d RxFL=%d RxDMA=%d\n",
+ card->devname,
+ sc->if_name,
+ sc->logic_ch_num,
+ i,
+ sc->wp_rx_complete_list.ifq_len,
+ sc->wp_rx_free_list.ifq_len,
+ sc->rx_dma);
+#endif
+
+#if 0
+{
+ unsigned long dma_descr;
+ unsigned int reg;
+ dma_descr=(sc->logic_ch_num<<4) + XILINX_RxDMA_DESCRIPTOR_HI;
+ sdla_bus_read_4(card->hw, dma_descr, &reg);
+ log(LOG_INFO, "%s: Hi Descriptor 0x%X\n",sc->if_name,reg);
+}
+#endif
+
+ bit_set((u_int8_t*)&sc->pkt_error, WP_FIFO_ERROR_BIT);
+
+ err=-EINVAL;
+ }
+ }
+ }
+
+ return err;
+}
+
+
+static void front_end_interrupt(sdla_t *card, unsigned long reg)
+{
+ sdla_te_intr(card);
+ handle_front_end_state(card);
+ return;
+}
+
+/**SECTION***************************************************************
+ *
+ * HARDWARE Interrupt Handlers
+ *
+ ***********************************************************************/
+
+
+/*============================================================================
+ * wan_xilinx_isr
+ *
+ * Main interrupt service routine.
+ * Determin the interrupt received and handle it.
+ *
+ */
+static void wp_xilinx_isr (sdla_t* card)
+{
+ int i;
+ u_int32_t reg;
+ u_int32_t dma_tx_reg,dma_rx_reg;
+ xilinx_softc_t *sc;
+
+ if (bit_test((u_int8_t*)&card->critical, CARD_DOWN)){
+ log(LOG_INFO, "%s: Card down, ignoring interrupt !!!!!!!!\n",
+ card->devname);
+ return;
+ }
+
+
+ bit_set((u_int8_t*)&card->in_isr, 0);
+
+/* write_cpld(card,LED_CONTROL_REG,0x0F);*/
+
+ /* -----------------2/6/2003 9:02AM------------------
+ * Disable all chip Interrupts (offset 0x040)
+ * -- "Transmit/Receive DMA Engine" interrupt disable
+ * -- "FiFo/Line Abort Error" interrupt disable
+ * --------------------------------------------------*/
+ sdla_bus_read_4(card->hw,XILINX_CHIP_CFG_REG, &reg);
+
+ if (bit_test((u_int8_t*)&reg, SECURITY_STATUS_FLAG)){
+ log(LOG_INFO, "%s: Critical: Chip Security Compromised!\n",
+ card->devname);
+ log(LOG_INFO, "%s: Disabling Driver!\n",
+ card->devname);
+ log(LOG_INFO, "%s: Please call Sangoma Tech Suppor!\n",
+ card->devname);
+ log(LOG_INFO, "%s: (www.sangoma.com)!\n",
+ card->devname);
+
+ port_set_state(card,WAN_DISCONNECTED);
+ disable_data_error_intr(card,CARD_DOWN);
+ goto isr_end;
+ }
+
+ /* Note: If interrupts are received without pending
+ ** flags, it usually indicates that the interrupt
+ ** is being shared. (Check 'cat /proc/interrupts') */
+ if (bit_test((u_int8_t*)&reg, FRONT_END_INTR_ENABLE_BIT)){
+ if (bit_test((u_int8_t*)&reg, FRONT_END_INTR_FLAG)){
+ front_end_interrupt(card,reg);
+ if (card->u.xilinx.state_change_exit_isr){
+ card->u.xilinx.state_change_exit_isr=0;
+ /* The state change occured, skip all
+ ** other interrupts */
+ goto isr_end;
+ }
+ }
+ }
+
+ /* Test Fifo Error Interrupt,
+ ** If set shutdown all interfaces and
+ ** reconfigure */
+ if (bit_test((u_int8_t*)&reg, ERROR_INTR_ENABLE_BIT)){
+ if (bit_test((u_int8_t*)&reg, ERROR_INTR_FLAG)){
+ fifo_error_interrupt(card,reg);
+ }
+ }
+
+ /* -----------------2/6/2003 9:37AM------------------
+ ** Checking for Interrupt source:
+ ** 1. Receive DMA Engine
+ ** 2. Transmit DMA Engine
+ ** 3. Error conditions.
+ ** --------------------------------------------------*/
+ if (bit_test((u_int8_t*)&reg, GLOBAL_INTR_ENABLE_BIT) &&
+ bit_test((u_int8_t*)&reg, DMA_INTR_FLAG)){
+
+
+ /* Receive DMA Engine */
+ sdla_bus_read_4(card->hw,
+ XILINX_DMA_RX_INTR_PENDING_REG,
+ &dma_rx_reg);
+
+ dma_rx_reg&=card->u.xilinx.active_ch_map;
+
+ if (dma_rx_reg == 0){
+ goto isr_rx;
+ }
+
+ for (i=0; i<card->u.xilinx.num_of_time_slots ;i++){
+ if (bit_test((u_int8_t*)&dma_rx_reg, i) &&
+ bit_test((u_int8_t*)&card->u.xilinx.logic_ch_map, i)){
+ sc=(xilinx_softc_t*)card->u.xilinx.dev_to_ch_map[i];
+ if (!sc){
+ log(LOG_INFO, "%s: Error: No Dev for Rx logical ch=%d\n",
+ card->devname,i);
+ continue;
+ }
+
+ xilinx_dma_rx_complete(card,sc);
+ }
+ }
+isr_rx:
+
+ /* Transmit DMA Engine */
+ sdla_bus_read_4(card->hw,
+ XILINX_DMA_TX_INTR_PENDING_REG,
+ &dma_tx_reg);
+
+ dma_tx_reg&=card->u.xilinx.active_ch_map;
+
+ if (dma_tx_reg == 0){
+ goto isr_tx;
+ }
+
+ for (i=0; i<card->u.xilinx.num_of_time_slots ;i++){
+ if (bit_test((u_int8_t*)&dma_tx_reg, i) &&
+ bit_test((u_int8_t*)&card->u.xilinx.logic_ch_map, i)){
+ sc=(xilinx_softc_t*)card->u.xilinx.dev_to_ch_map[i];
+ if (!sc){
+ log(LOG_INFO, "%s: Error: No Dev for Tx logical ch=%d\n",
+ card->devname,i);
+ continue;
+ }
+
+ xilinx_dma_tx_complete(card,sc);
+ }
+ }
+ }
+
+isr_tx:
+
+ /* -----------------2/6/2003 10:36AM-----------------
+ * Finish of the interupt handler
+ * --------------------------------------------------*/
+isr_end:
+
+/* write_cpld(card,LED_CONTROL_REG,0x0E); */
+
+ bit_clear((u_int8_t*)&card->in_isr, 0);
+ return;
+}
+
+
+/**SECTION*************************************************************
+ *
+ * TASK Functions and Triggers
+ *
+ **********************************************************************/
+
+
+/*============================================================================
+ * port_set_state
+ *
+ * Set PORT state.
+ *
+ */
+static void port_set_state (sdla_t *card, int state)
+{
+ wanpipe_common_t *common;
+
+ if (card->state != state){
+ switch (state){
+ case WAN_CONNECTED:
+ log(LOG_INFO, "%s: Link connected!\n",
+ card->devname);
+ aft_red_led_ctrl(card,AFT_LED_OFF);
+ aft_green_led_ctrl(card,AFT_LED_ON);
+ break;
+
+ case WAN_CONNECTING:
+ log(LOG_INFO, "%s: Link connecting...\n",
+ card->devname);
+ aft_red_led_ctrl(card,AFT_LED_ON);
+ aft_green_led_ctrl(card,AFT_LED_OFF);
+ break;
+
+ case WAN_DISCONNECTED:
+ log(LOG_INFO, "%s: Link disconnected!\n",
+ card->devname);
+ aft_red_led_ctrl(card,AFT_LED_ON);
+ aft_green_led_ctrl(card,AFT_LED_OFF);
+ break;
+ }
+ card->state = state;
+ LIST_FOREACH(common, &card->dev_head, next){
+ struct ifnet* ifp = (struct ifnet*)&common->ifp;
+ if (ifp){
+ set_chan_state(card, ifp, state);
+ }
+ }
+ }
+}
+
+
+/*============================================================
+ * handle_front_end_state
+ *
+ *
+ */
+
+static void handle_front_end_state(void *card_id)
+{
+ sdla_t* card = (sdla_t*)card_id;
+
+ if (card->front_end_status == FE_CONNECTED){
+ enable_data_error_intr(card);
+ port_set_state(card,WAN_CONNECTED);
+ card->u.xilinx.state_change_exit_isr=1;
+ }else{
+ port_set_state(card,WAN_CONNECTING);
+ disable_data_error_intr(card,LINK_DOWN);
+ card->u.xilinx.state_change_exit_isr=1;
+ }
+}
+
+static unsigned char read_cpld(sdla_t *card, unsigned short cpld_off)
+{
+ u_int16_t org_off;
+ u_int8_t tmp;
+
+ cpld_off &= ~BIT_DEV_ADDR_CLEAR;
+ cpld_off |= BIT_DEV_ADDR_CPLD;
+
+ /* Save the current address. */
+ sdla_bus_read_2(card->hw,
+ XILINX_MCPU_INTERFACE_ADDR,
+ &org_off);
+
+ sdla_bus_write_2(card->hw,
+ XILINX_MCPU_INTERFACE_ADDR,
+ cpld_off);
+
+ sdla_bus_read_1(card->hw,XILINX_MCPU_INTERFACE, &tmp);
+
+ /* Restore original address */
+ sdla_bus_write_2(card->hw,
+ XILINX_MCPU_INTERFACE_ADDR,
+ org_off);
+ return tmp;
+}
+
+static unsigned char
+write_cpld(sdla_t *card, unsigned short off,unsigned char data)
+{
+ u_int16_t org_off;
+
+ off &= ~BIT_DEV_ADDR_CLEAR;
+ off |= BIT_DEV_ADDR_CPLD;
+
+ /* Save the current original address */
+ sdla_bus_read_2(card->hw,
+ XILINX_MCPU_INTERFACE_ADDR,
+ &org_off);
+
+ sdla_bus_write_2(card->hw,
+ XILINX_MCPU_INTERFACE_ADDR,
+ off);
+
+ /* This delay is required to avoid bridge optimization
+ * (combining two writes together)*/
+ DELAY(5);
+
+ sdla_bus_write_1(card->hw,
+ XILINX_MCPU_INTERFACE,
+ data);
+
+ /* This delay is required to avoid bridge optimization
+ * (combining two writes together)*/
+ DELAY(5);
+
+ /* Restore the original address */
+ sdla_bus_write_2(card->hw,
+ XILINX_MCPU_INTERFACE_ADDR,
+ org_off);
+ return 0;
+}
+
+static unsigned char
+write_front_end_reg(void* card1, unsigned short off, unsigned char value)
+{
+ sdla_t* card = (sdla_t*)card1;
+
+ off &= ~BIT_DEV_ADDR_CLEAR;
+ sdla_bus_write_2(card->hw,XILINX_MCPU_INTERFACE_ADDR, off);
+ /* AF: Sep 10, 2003
+ * IMPORTANT
+ * This delays are required to avoid bridge optimization
+ * (combining two writes together)
+ */
+ DELAY(5);
+ sdla_bus_write_1(card->hw,XILINX_MCPU_INTERFACE, value);
+ DELAY(5);
+
+ return 0;
+}
+
+
+/*=======================================================================
+ * Read TE1/56K Front end registers
+ */
+static unsigned char read_front_end_reg (void* card1, unsigned short off)
+{
+ sdla_t* card = (sdla_t*)card1;
+ u_int8_t tmp;
+
+ off &= ~BIT_DEV_ADDR_CLEAR;
+ sdla_bus_write_2(card->hw, XILINX_MCPU_INTERFACE_ADDR, off);
+ sdla_bus_read_1(card->hw,XILINX_MCPU_INTERFACE, &tmp);
+ DELAY(5);
+
+ return tmp;
+}
+
+
+/*=========================================
+ * enable_data_error_intr
+ *
+ * Description:
+ *
+ * Run only after the front end comes
+ * up from down state.
+ *
+ * Clean the DMA Tx/Rx pending interrupts.
+ * (Ignore since we will reconfigure
+ * all dma descriptors. DMA controler
+ * was already disabled on link down)
+ *
+ * For all channels clean Tx/Rx Fifo
+ *
+ * Enable DMA controler
+ * (This starts the fifo cleaning
+ * process)
+ *
+ * For all channels reprogram Tx/Rx DMA
+ * descriptors.
+ *
+ * Clean the Tx/Rx Error pending interrupts.
+ * (Since dma fifo's are now empty)
+ *
+ * Enable global DMA and Error interrutps.
+ *
+ */
+
+static void enable_data_error_intr(sdla_t *card)
+{
+ wanpipe_common_t *common;
+ struct ifnet *ifp;
+ u_int32_t reg;
+
+ /* Clean Tx/Rx DMA interrupts */
+ sdla_bus_read_4(card->hw,
+ XILINX_DMA_RX_INTR_PENDING_REG, &reg);
+ sdla_bus_read_4(card->hw,
+ XILINX_DMA_TX_INTR_PENDING_REG, &reg);
+
+
+ /* For all channels clean Tx/Rx fifos */
+ LIST_FOREACH(common, &card->dev_head, next){
+ xilinx_softc_t *sc;
+
+ ifp = (struct ifnet*)&common->ifp;
+ if (!ifp || !ifp->if_softc)
+ continue;
+ sc = ifp->if_softc;
+#if 0
+ if (!(ifp->if_flags & IFF_UP)){
+ continue;
+ }
+#endif
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Init interface fifo no wait %s\n",
+ sc->if_name, __FUNCTION__);
+#endif
+ xilinx_init_rx_dev_fifo(card, sc, WP_NO_WAIT);
+ xilinx_init_tx_dev_fifo(card, sc, WP_NO_WAIT);
+ }
+
+ /* Enable DMA controler, in order to start the
+ ** fifo cleaning */
+ sdla_bus_read_4(card->hw,XILINX_DMA_CONTROL_REG,&reg);
+ bit_set((u_int8_t*)&reg, DMA_ENGINE_ENABLE_BIT);
+ sdla_bus_write_4(card->hw,XILINX_DMA_CONTROL_REG,reg);
+
+ /* For all channels clean Tx/Rx fifos */
+ LIST_FOREACH(common, &card->dev_head, next){
+ xilinx_softc_t *sc;
+
+ ifp = (struct ifnet*)&common->ifp;
+ if (!ifp || ifp->if_softc == NULL)
+ continue;
+ sc = ifp->if_softc;
+#if 0
+ if (!(ifp->if_flags & IFF_UP)){
+ continue;
+ }
+#endif
+
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Init interface fifo %s\n",
+ sc->if_name, __FUNCTION__);
+#endif
+
+ xilinx_init_rx_dev_fifo(card, sc, WP_WAIT);
+ xilinx_init_tx_dev_fifo(card, sc, WP_WAIT);
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Clearing Fifo and idle_flag %s\n",
+ card->devname,sc->if_name);
+#endif
+ bit_clear((u_int8_t*)&sc->idle_start, 0);
+ }
+
+ /* For all channels, reprogram Tx/Rx DMA descriptors.
+ * For Tx also make sure that the BUSY flag is clear
+ * and previoulsy Tx packet is deallocated */
+
+ LIST_FOREACH(common, &card->dev_head, next){
+ xilinx_softc_t *sc;
+
+ ifp = (struct ifnet*)&common->ifp;
+ if (!ifp || !ifp->if_softc)
+ continue;
+ sc = ifp->if_softc;
+#if 0
+ if (!(ifp->if_flags & IFF_UP)){
+ continue;
+ }
+#endif
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Init interface %s\n",
+ sc->if_name, __FUNCTION__);
+#endif
+
+ if (sc->rx_dma_mbuf){
+ wp_rx_element_t *rx_el;
+ struct mbuf *m=sc->rx_dma_mbuf;
+
+ sc->rx_dma_mbuf=NULL;
+ rx_el = mtod(m, wp_rx_element_t *);
+ aft_init_requeue_free_m(sc, m);
+ }
+
+ xilinx_dma_rx(card,sc);
+
+ if (sc->tx_dma_addr && sc->tx_dma_len){
+ sc->tx_dma_addr=0;
+ sc->tx_dma_len=0;
+ }
+
+ if (sc->tx_dma_mbuf){
+ m_freem(sc->tx_dma_mbuf);
+ sc->tx_dma_mbuf=NULL;
+ }
+
+ bit_clear((u_int8_t*)&sc->dma_status, TX_BUSY);
+ bit_clear((u_int8_t*)&sc->idle_start, 0);
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Clearing Fifo and idle_flag %s\n",
+ card->devname,sc->if_name);
+#endif
+ }
+
+ /* Clean Tx/Rx Error interrupts, since fifos are now
+ * empty, and Tx fifo may generate an underrun which
+ * we want to ignore :) */
+ sdla_bus_read_4(card->hw,
+ XILINX_HDLC_RX_INTR_PENDING_REG, &reg);
+ sdla_bus_read_4(card->hw,
+ XILINX_HDLC_TX_INTR_PENDING_REG, &reg);
+
+ /* Enable Global DMA and Error Interrupts */
+
+ reg=0;
+ sdla_bus_read_4(card->hw,XILINX_CHIP_CFG_REG,&reg);
+ bit_set((u_int8_t*)&reg, GLOBAL_INTR_ENABLE_BIT);
+ bit_set((u_int8_t*)&reg, ERROR_INTR_ENABLE_BIT);
+ sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg);
+
+ return;
+}
+
+static void disable_data_error_intr(sdla_t *card, unsigned char event)
+{
+ u_int32_t reg;
+
+ sdla_bus_read_4(card->hw,XILINX_CHIP_CFG_REG,&reg);
+ bit_clear((u_int8_t*)&reg, GLOBAL_INTR_ENABLE_BIT);
+ bit_clear((u_int8_t*)&reg, ERROR_INTR_ENABLE_BIT);
+ if (event==DEVICE_DOWN){
+ bit_clear((u_int8_t*)&reg, FRONT_END_INTR_ENABLE_BIT);
+ }
+ sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg);
+
+ sdla_bus_read_4(card->hw,XILINX_DMA_CONTROL_REG,&reg);
+ bit_clear((u_int8_t*)&reg, DMA_ENGINE_ENABLE_BIT);
+ sdla_bus_write_4(card->hw,XILINX_DMA_CONTROL_REG,reg);
+
+}
+
+static void xilinx_init_tx_dma_descr(sdla_t *card, xilinx_softc_t *sc)
+{
+ unsigned long dma_descr;
+ unsigned long reg=0;
+
+ dma_descr=(sc->logic_ch_num<<4) + XILINX_TxDMA_DESCRIPTOR_HI;
+ sdla_bus_write_4(card->hw,dma_descr, reg);
+}
+
+
+
+static void xilinx_tx_fifo_under_recover (sdla_t *card, xilinx_softc_t *sc)
+{
+ struct ifnet *ifp = (struct ifnet*)&sc->common.ifp;
+ u_int32_t reg=0;
+ unsigned long dma_descr;
+
+#if defined(DEBUG_ERR)
+ log(LOG_INFO, "%s:%s: Tx Fifo Recovery \n",
+ card->devname,sc->if_name);
+#endif
+
+ /* Initialize Tx DMA descriptor: Stop DMA */
+ dma_descr=(sc->logic_ch_num<<4) + XILINX_TxDMA_DESCRIPTOR_HI;
+ sdla_bus_write_4(card->hw,dma_descr, reg);
+
+ /* Clean the TX FIFO */
+ xilinx_init_tx_dev_fifo(card, sc, WP_WAIT);
+ if (sc->tx_dma_addr && sc->tx_dma_len){
+ sc->tx_dma_addr=0;
+ sc->tx_dma_len=0;
+ }
+
+ /* Requeue the current tx packet, for
+ ** re-transmission */
+ if (sc->tx_dma_mbuf){
+ IF_PREPEND(&sc->wp_tx_pending_list,
+ (struct mbuf*)sc->tx_dma_mbuf);
+ sc->tx_dma_mbuf=NULL;
+ }
+
+ /* Wake up the stack, because tx dma interrupt
+ ** failed */
+ if (ifp) ifp->if_oerrors++;
+
+#if defined(DEBUG_ERR)
+ log(LOG_INFO, "%s:%s: Tx Fifo Recovery: Restarting Transmission \n",
+ card->devname,sc->if_name);
+#endif
+
+ /* Re-start transmission */
+ bit_clear((u_int8_t*)&sc->dma_status, TX_BUSY);
+ if (!xilinx_dma_tx(card,sc)){
+ /* If we was able to transmit and the interface is set
+ ** to OACTIVE remove this flag and let kernel try to
+ ** transmit. */
+ if (ifp->if_flags & IFF_OACTIVE){
+ ifp->if_flags &= ~IFF_OACTIVE;
+ }
+ }
+ return;
+}
+
+static int
+xilinx_write_ctrl_hdlc(sdla_t *card, u_int32_t timeslot, u_int8_t reg_off, u_int32_t data)
+{
+ u_int32_t reg;
+ u_int32_t ts_orig=timeslot;
+ unsigned long timeout=ticks;
+
+ if (timeslot == 0){
+ timeslot=card->u.xilinx.num_of_time_slots-2;
+ }else if (timeslot == 1){
+ timeslot=card->u.xilinx.num_of_time_slots-1;
+ }else{
+ timeslot-=2;
+ }
+
+ timeslot=timeslot<<XILINX_CURRENT_TIMESLOT_SHIFT;
+ timeslot&=XILINX_CURRENT_TIMESLOT_MASK;
+
+ for (;;){
+ sdla_bus_read_4(card->hw,XILINX_TIMESLOT_HDLC_CHAN_REG,&reg);
+ reg&=XILINX_CURRENT_TIMESLOT_MASK;
+
+ if (reg == timeslot){
+ sdla_bus_write_4(card->hw,reg_off,data);
+ return 0;
+ }
+
+ if ((ticks-timeout) > 1){
+ log(LOG_INFO,
+ "%s: Error: Access to timeslot %d timed out!\n",
+ card->devname,ts_orig);
+ return -EIO;
+ }
+ }
+
+ return -EIO;
+}
+
+static int set_chan_state(sdla_t* card, struct ifnet* ifp, int state)
+{
+ xilinx_softc_t *sc = ifp->if_softc;
+
+ if (sc == NULL){
+ return 0;
+ }
+ if (state == WAN_CONNECTED){
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Setting idle_start to 0\n",
+ sc->if_name);
+#endif
+ bit_clear((u_int8_t*)&sc->idle_start, 0);
+ }
+
+ return 0;
+}
+
+
+static char fifo_size_vector[] = {1, 2, 4, 8, 16, 32};
+static char fifo_code_vector[] = {0, 1, 3, 7,0xF,0x1F};
+
+static int request_fifo_baddr_and_size(sdla_t *card, xilinx_softc_t *sc)
+{
+ unsigned char req_fifo_size,fifo_size;
+ int i;
+
+ /* Calculate the optimal fifo size based
+ * on the number of time slots requested */
+
+ if (IS_T1(&card->fe_te.te_cfg)){
+
+ if (sc->num_of_time_slots == NUM_OF_T1_CHANNELS){
+ req_fifo_size=32;
+ }else if (sc->num_of_time_slots == 1){
+ req_fifo_size=1;
+ }else if (sc->num_of_time_slots == 2 ||
+ sc->num_of_time_slots == 3){
+ req_fifo_size=2;
+ }else if (sc->num_of_time_slots >= 4 &&
+ sc->num_of_time_slots<= 7){
+ req_fifo_size=4;
+ }else if (sc->num_of_time_slots >= 8 &&
+ sc->num_of_time_slots<= 15){
+ req_fifo_size=8;
+ }else if (sc->num_of_time_slots >= 16 &&
+ sc->num_of_time_slots<= 23){
+ req_fifo_size=16;
+ }else{
+ log(LOG_INFO, "%s: Invalid number of timeslots %d\n",
+ card->devname,
+ sc->num_of_time_slots);
+ return -EINVAL;
+ }
+ }else{
+ if (sc->num_of_time_slots == (NUM_OF_E1_CHANNELS-1)){
+ req_fifo_size=32;
+ }else if (sc->num_of_time_slots == 1){
+ req_fifo_size=1;
+ }else if (sc->num_of_time_slots == 2 ||
+ sc->num_of_time_slots == 3){
+ req_fifo_size=2;
+ }else if (sc->num_of_time_slots >= 4 &&
+ sc->num_of_time_slots <= 7){
+ req_fifo_size=4;
+ }else if (sc->num_of_time_slots >= 8 &&
+ sc->num_of_time_slots <= 15){
+ req_fifo_size=8;
+ }else if (sc->num_of_time_slots >= 16 &&
+ sc->num_of_time_slots <= 31){
+ req_fifo_size=16;
+ }else{
+ log(LOG_INFO,
+ "%s:%s: Invalid number of timeslots %d\n",
+ card->devname,
+ sc->if_name,
+ sc->num_of_time_slots);
+ return -EINVAL;
+ }
+ }
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s:%s: Optimal Fifo Size =%d Timeslots=%d \n",
+ card->devname,
+ sc->if_name,
+ req_fifo_size,
+ sc->num_of_time_slots);
+#endif
+ fifo_size=map_fifo_baddr_and_size(card,
+ req_fifo_size,
+ &sc->fifo_base_addr);
+ if (fifo_size == 0 || sc->fifo_base_addr == 31){
+ log(LOG_INFO,
+ "%s:%s: Error: Failed to obtain fifo size %d or addr %d\n",
+ card->devname,
+ sc->if_name,
+ fifo_size,
+ sc->fifo_base_addr);
+ return -EINVAL;
+ }
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s:%s: Optimal Fifo Size =%d TS=%d New Fifo Size=%d\n",
+ card->devname,
+ sc->if_name,
+ req_fifo_size,
+ sc->num_of_time_slots,
+ fifo_size);
+#endif
+
+ for (i=0;i<sizeof(fifo_size_vector);i++){
+ if (fifo_size_vector[i] == fifo_size){
+ sc->fifo_size_code=fifo_code_vector[i];
+ break;
+ }
+ }
+
+ if (fifo_size != req_fifo_size){
+ log(LOG_INFO,
+ "%s:%s: WARN: Failed to obtain the req fifo %d got %d\n",
+ card->devname,
+ sc->if_name,
+ req_fifo_size,
+ fifo_size);
+ }
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: %s:Fifo Size=%d TS=%d Fifo Code=%d Addr=%d\n",
+ card->devname,sc->if_name,fifo_size,
+ sc->num_of_time_slots,sc->fifo_size_code,
+ sc->fifo_base_addr);
+#endif
+ sc->fifo_size = fifo_size;
+
+ return 0;
+}
+
+
+static int
+map_fifo_baddr_and_size(sdla_t *card, unsigned char fifo_size, unsigned char *addr)
+{
+ u_int32_t reg=0;
+ int i;
+
+ for (i=0;i<fifo_size;i++){
+ bit_set((u_int8_t*)&reg, i);
+ }
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Trying to MAP 0x%X to 0x%lX\n",
+ card->devname,reg,card->u.xilinx.fifo_addr_map);
+#endif
+ for (i=0;i<32;i+=fifo_size){
+ if (card->u.xilinx.fifo_addr_map & (reg<<i)){
+ continue;
+ }
+ card->u.xilinx.fifo_addr_map |= reg<<i;
+ *addr=i;
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Card fifo Map 0x%lX Addr =%d\n",
+ card->devname,card->u.xilinx.fifo_addr_map,i);
+#endif
+ return fifo_size;
+ }
+
+ if (fifo_size == 1){
+ return 0;
+ }
+
+ fifo_size = fifo_size >> 1;
+
+ return map_fifo_baddr_and_size(card,fifo_size,addr);
+}
+
+
+static int free_fifo_baddr_and_size (sdla_t *card, xilinx_softc_t *sc)
+{
+ u_int32_t reg=0;
+ int i;
+
+ for (i=0;i<sc->fifo_size;i++){
+ bit_set((u_int8_t*)&reg, i);
+ }
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: Unmapping 0x%X from 0x%lX\n",
+ card->devname,
+ reg<<sc->fifo_base_addr,
+ card->u.xilinx.fifo_addr_map);
+#endif
+ card->u.xilinx.fifo_addr_map &= ~(reg<<sc->fifo_base_addr);
+
+#if defined(DEBUG_INIT)
+ log(LOG_INFO, "%s: New Map is 0x%lX\n",
+ card->devname, card->u.xilinx.fifo_addr_map);
+#endif
+
+ sc->fifo_size=0;
+ sc->fifo_base_addr=0;
+
+ return 0;
+}
+
+static void aft_red_led_ctrl(sdla_t *card, int mode)
+{
+ unsigned int led;
+
+ sdla_bus_read_4(card->hw,XILINX_CHIP_CFG_REG, &led);
+
+ if (mode == AFT_LED_ON){
+ bit_clear((u_int8_t*)&led, XILINX_RED_LED);
+ }else if (mode == AFT_LED_OFF){
+ bit_set((u_int8_t*)&led, XILINX_RED_LED);
+ }else{
+ if (bit_test((u_int8_t*)&led, XILINX_RED_LED)){
+ bit_clear((u_int8_t*)&led, XILINX_RED_LED);
+ }else{
+ bit_set((u_int8_t*)&led, XILINX_RED_LED);
+ }
+ }
+
+ sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG, led);
+}
+
+static void aft_led_timer(void *data)
+{
+ sdla_t *card=(sdla_t*)data;
+ unsigned int te_alarm;
+
+ if (bit_test((u_int8_t*)&card->critical, CARD_DOWN)){
+ return;
+ }
+
+ if (IS_TE1(&card->fe_te.te_cfg)) {
+ int s = splnet();
+
+ te_alarm = sdla_te_alarm(card, 0);
+ te_alarm&=~(BIT_OOSMF_ALARM|BIT_OOCMF_ALARM);
+
+ if (!te_alarm){
+ if (card->state == WAN_CONNECTED){
+ aft_red_led_ctrl(card, AFT_LED_OFF);
+ aft_green_led_ctrl(card, AFT_LED_ON);
+ }else{
+ aft_red_led_ctrl(card, AFT_LED_OFF);
+ aft_green_led_ctrl(card, AFT_LED_TOGGLE);
+ }
+
+ }else if (te_alarm & (BIT_RED_ALARM|BIT_LOS_ALARM)){
+ /* Red or LOS Alarm solid RED */
+ aft_red_led_ctrl(card, AFT_LED_ON);
+ aft_green_led_ctrl(card, AFT_LED_OFF);
+ }else if (te_alarm & BIT_OOF_ALARM){
+ /* OOF Alarm flashing RED */
+ aft_red_led_ctrl(card, AFT_LED_TOGGLE);
+ aft_green_led_ctrl(card, AFT_LED_OFF);
+ }else if (te_alarm & BIT_AIS_ALARM){
+ /* AIS - Blue Alarm flasing RED and GREEN */
+ aft_red_led_ctrl(card, AFT_LED_TOGGLE);
+ aft_green_led_ctrl(card, AFT_LED_TOGGLE);
+ }else if (te_alarm & BIT_YEL_ALARM){
+ /* Yellow Alarm */
+ aft_red_led_ctrl(card, AFT_LED_ON);
+ aft_green_led_ctrl(card, AFT_LED_ON);
+ }else{
+
+ /* Default case shouldn't happen */
+ log(LOG_INFO, "%s: Unknown Alarm 0x%X\n",
+ card->devname,te_alarm);
+ aft_red_led_ctrl(card, AFT_LED_ON);
+ aft_green_led_ctrl(card, AFT_LED_ON);
+ }
+
+ splx(s);
+ timeout_add(&card->u.xilinx.led_timer,hz);
+ }
+}
+
+
+int aft_core_ready(sdla_t *card)
+{
+ u_int32_t reg;
+ volatile unsigned char cnt=0;
+
+ for (;;){
+ sdla_bus_read_4(card->hw,XILINX_CHIP_CFG_REG, &reg);
+ if (!bit_test((u_int8_t*)&reg, HDLC_CORE_READY_FLAG_BIT)){
+ /* The HDLC Core is not ready! we have
+ ** an error. */
+ if (++cnt > 5){
+ return -EINVAL;
+ }else{
+ DELAY(500);
+ /* WARNING: we cannot do this while in
+ * critical area */
+ }
+ }else{
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+
+/****** End ****************************************************************/
diff --git a/sys/dev/pci/if_san_xilinx.h b/sys/dev/pci/if_san_xilinx.h
new file mode 100644
index 00000000000..fcb108ed26a
--- /dev/null
+++ b/sys/dev/pci/if_san_xilinx.h
@@ -0,0 +1,667 @@
+/*-
+ * Copyright (c) 2001-2004 Sangoma Technologies (SAN)
+ * All rights reserved. www.sangoma.com
+ *
+ * This code is written by Nenad Corbic <ncorbic@sangoma.com> for SAN.
+ * The code is derived from permitted modifications to software created
+ * by Alex Feldman (al.feldman@sangoma.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sangoma Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SANGOMA TECHNOLOGIES AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __IF_SAN_XILINX_H
+#define __IF_SAN_XILINX_H
+
+
+
+
+
+#define XILINX_CHIP_CFG_REG 0x40
+
+
+#define XILINX_MCPU_INTERFACE 0x44
+#define XILINX_MCPU_INTERFACE_ADDR 0x46
+
+#define XILINX_GLOBAL_INTER_MASK 0x4C
+
+
+#define XILINX_HDLC_TX_INTR_PENDING_REG 0x50
+#define XILINX_HDLC_RX_INTR_PENDING_REG 0x54
+
+
+
+enum {
+ WP_FIFO_ERROR_BIT,
+ WP_CRC_ERROR_BIT,
+ WP_ABORT_ERROR_BIT,
+};
+
+
+#define WP_MAX_FIFO_FRAMES 7
+
+
+
+#define XILINX_DMA_TX_INTR_PENDING_REG 0x58
+#define XILINX_DMA_RX_INTR_PENDING_REG 0x5C
+
+
+
+#define XILINX_TIMESLOT_HDLC_CHAN_REG 0x60
+
+
+#define AFT_T3_RXTX_ADDR_SELECT_REG 0x60
+
+#define XILINX_CURRENT_TIMESLOT_MASK 0x00001F00
+#define XILINX_CURRENT_TIMESLOT_SHIFT 8
+
+
+#define XILINX_HDLC_CONTROL_REG 0x64
+
+
+#define XILINX_HDLC_ADDR_REG 0x68
+
+
+
+#define XILINX_CONTROL_RAM_ACCESS_BUF 0x6C
+
+
+
+#define XILINX_DMA_CONTROL_REG 0x70
+
+
+#define XILINX_DMA_TX_STATUS_REG 0x74
+
+
+#define AFT_TE3_TX_WDT_CTRL_REG 0x74
+
+
+#define XILINX_DMA_RX_STATUS_REG 0x78
+
+
+#define AFT_TE3_RX_WDT_CTRL_REG 0x78
+
+
+#define XILINX_DMA_DATA_REG 0x7C
+
+
+
+#define AFT_TE3_CRNT_DMA_DESC_ADDR_REG 0x80
+
+
+
+#define XILINX_TxDMA_DESCRIPTOR_LO 0x100
+#define XILINX_TxDMA_DESCRIPTOR_HI 0x104
+#define XILINX_RxDMA_DESCRIPTOR_LO 0x108
+#define XILINX_RxDMA_DESCRIPTOR_HI 0x10C
+
+
+
+
+
+
+
+
+#define INTERFACE_TYPE_T1_E1_BIT 0
+#define INTERFACE_TYPE_T3_E3_BIT 0
+
+
+#define XILINX_RED_LED 1
+
+
+#define AFT_T3_HDLC_TRANS_MODE 1
+
+
+#define FRONT_END_FRAME_FLAG_ENABLE_BIT 2
+
+
+#define AFT_T3_CLOCK_MODE 2
+
+
+
+#define SIGNALLING_ENABLE_BIT 3
+
+
+#define FRONT_END_RESET_BIT 4
+
+
+#define CHIP_RESET_BIT 5
+
+
+#define HDLC_CORE_RESET_BIT 6
+
+
+#define HDLC_CORE_READY_FLAG_BIT 7
+
+
+#define GLOBAL_INTR_ENABLE_BIT 8
+
+
+#define ERROR_INTR_ENABLE_BIT 9
+
+
+#define FRONT_END_INTR_ENABLE_BIT 10
+
+
+#define CHIP_ERROR_MASK 0x00FF0000
+
+
+#define AFT_TE3_TX_WDT_INTR_PND 26
+
+
+
+#define AFT_TE3_RX_WDT_INTR_PND 27
+
+
+
+#define FRONT_END_INTR_FLAG 28
+
+
+#define SECURITY_STATUS_FLAG 29
+
+
+#define ERROR_INTR_FLAG 30
+
+
+
+#define DMA_INTR_FLAG 31
+
+
+#define XILINX_GLOBAL_INTER_STATUS 0xD0000000
+
+
+
+
+
+#define TIMESLOT_BIT_SHIFT 16
+#define TIMESLOT_BIT_MASK 0x001F0000
+#define HDLC_LOGIC_CH_BIT_MASK 0x0000001F
+
+#define HDLC_LCH_TIMESLOT_MASK 0x001F001F
+
+
+
+
+
+
+#define HDLC_RX_CHAN_ENABLE_BIT 0
+
+
+#define HDLC_RX_FRAME_DATA_BIT 1
+
+
+#define HDLC_RC_CHAN_ACTIVE_BIT 2
+
+
+#define HDLC_RX_FRAME_ERROR_BIT 3
+
+
+#define HDLC_RX_FRAME_ABORT_BIT 4
+
+
+
+
+
+
+#define HDLC_RX_PROT_DISABLE_BIT 16
+
+
+#define HDLC_RX_ADDR_RECOGN_DIS_BIT 17
+
+
+#define HDLC_RX_ADDR_FIELD_DISC_BIT 18
+
+
+#define HDLC_RX_ADDR_SIZE_BIT 19
+
+
+#define HDLC_RX_BRD_ADDR_MATCH_BIT 20
+
+
+#define HDLC_RX_FCS_SIZE_BIT 21
+
+
+
+#define HDLC_CORE_RX_IDLE_LINE_BIT 22
+
+
+#define HDLC_CODE_RX_ABORT_LINE_BIT 23
+
+
+
+
+
+
+#define HDLC_TX_CHAN_ENABLE_BIT 24
+
+
+#define HDLC_TX_PROT_DISABLE_BIT 25
+
+
+
+#define HDLC_TX_ADDR_INSERTION_BIT 26
+
+
+
+#define HDLC_TX_ADDR_SIZE_BIT 27
+
+
+
+#define HDLC_TX_FCS_SIZE_BIT 28
+
+
+#define HDLC_TX_FRAME_ABORT_BIT 29
+
+
+#define HDLC_TX_STOP_TX_ON_ABORT_BIT 30
+
+
+#define HDLC_TX_CHANNEL_ACTIVE_BIT 31
+
+
+
+
+
+#define CONTROL_RAM_DATA_MASK 0x0000001F
+
+
+#define HDLC_FIFO_BASE_ADDR_SHIFT 16
+#define HDLC_FIFO_BASE_ADDR_MASK 0x1F
+
+
+#define HDLC_FIFO_SIZE_SHIFT 8
+#define HDLC_FIFO_SIZE_MASK 0x1F
+
+#define HDLC_FREE_LOGIC_CH 31
+#define TRANSPARENT_MODE_BIT 31
+
+
+
+#define DMA_SIZE_BIT_SHIFT 0
+
+
+#define DMA_FIFO_HI_MARK_BIT_SHIFT 4
+
+
+#define DMA_FIFO_LO_MARK_BIT_SHIFT 8
+#define DMA_FIFO_T3_MARK_BIT_SHIFT 8
+
+
+#define DMA_ACTIVE_CHANNEL_BIT_SHIFT 16
+#define DMA_ACTIVE_CHANNEL_BIT_MASK 0xFFE0FFFF
+
+
+#define DMA_ENGINE_ENABLE_BIT 31
+
+
+#define DMA_CHAIN_TE3_MASK 0x0000000F
+
+
+
+
+#define TxDMA_LO_PC_ADDR_PTR_BIT_MASK 0xFFFFFFFC
+
+
+
+#define TxDMA_LO_ALIGNMENT_BIT_MASK 0x00000003
+
+
+
+#define TxDMA_HI_DMA_DATA_LENGTH_MASK 0x000007FF
+
+
+#define TxDMA_HI_DMA_PCI_ERROR_MASK 0x00007800
+#define TxDMA_HI_DMA_PCI_ERROR_M_ABRT 0x00000800
+#define TxDMA_HI_DMA_PCI_ERROR_T_ABRT 0x00001000
+#define TxDMA_HI_DMA_PCI_ERROR_DS_TOUT 0x00002000
+#define TxDMA_HI_DMA_PCI_ERROR_RETRY_TOUT 0x00004000
+
+
+#define INIT_DMA_FIFO_CMD_BIT 28
+
+
+
+#define TxDMA_HI_DMA_FRAME_START_BIT 30
+
+
+
+#define TxDMA_HI_DMA_FRAME_END_BIT 29
+
+
+#define TxDMA_HI_DMA_GO_READY_BIT 31
+
+
+
+#define DMA_FIFO_BASE_ADDR_SHIFT 20
+#define DMA_FIFO_BASE_ADDR_MASK 0x1F
+
+
+#define DMA_FIFO_SIZE_SHIFT 15
+#define DMA_FIFO_SIZE_MASK 0x1F
+
+
+#define DMA_FIFO_PARAM_CLEAR_MASK 0xFE007FFF
+
+#define FIFO_32B 0x00
+#define FIFO_64B 0x01
+#define FIFO_128B 0x03
+#define FIFO_256B 0x07
+#define FIFO_512B 0x0F
+#define FIFO_1024B 0x1F
+
+
+
+
+
+#define RxDMA_LO_PC_ADDR_PTR_BIT_MASK 0xFFFFFFFC
+
+
+
+#define RxDMA_LO_ALIGNMENT_BIT_MASK 0x00000003
+
+
+
+#define RxDMA_HI_DMA_DATA_LENGTH_MASK 0x000007FF
+
+
+#define RxDMA_HI_DMA_PCI_ERROR_MASK 0x00007800
+#define RxDMA_HI_DMA_PCI_ERROR_M_ABRT 0x00000800
+#define RxDMA_HI_DMA_PCI_ERROR_T_ABRT 0x00001000
+#define RxDMA_HI_DMA_PCI_ERROR_DS_TOUT 0x00002000
+#define RxDMA_HI_DMA_PCI_ERROR_RETRY_TOUT 0x00004000
+
+
+
+#define RxDMA_HI_DMA_COMMAND_BIT_SHIFT 28
+
+
+
+#define RxDMA_HI_DMA_FRAME_START_BIT 30
+
+
+
+#define RxDMA_HI_DMA_CRC_ERROR_BIT 25
+
+
+
+#define RxDMA_HI_DMA_FRAME_ABORT_BIT 26
+
+
+
+#define RxDMA_HI_DMA_FRAME_END_BIT 29
+
+
+#define RxDMA_HI_DMA_GO_READY_BIT 31
+
+
+
+#define DMA_HI_TE3_INTR_DISABLE_BIT 27
+
+
+#define DMA_HI_TE3_NOT_LAST_FRAME_BIT 24
+
+
+
+
+#define AFT_TE3_CRNT_TX_DMA_MASK 0x0000000F
+
+#define AFT_TE3_CRNT_RX_DMA_MASK 0x000000F0
+#define AFT_TE3_CRNT_RX_DMA_SHIFT 4
+
+
+
+
+
+
+
+typedef struct xilinx_config
+{
+ unsigned long xilinx_chip_cfg_reg;
+ unsigned long xilinx_dma_control_reg;
+
+}xilinx_config_t;
+
+
+
+#define XILINX_DMA_SIZE 10
+
+
+#define XILINX_DMA_FIFO_UP 8
+
+
+#define XILINX_DMA_FIFO_LO 8
+
+
+#define AFT_T3_DMA_FIFO_MARK 8
+
+
+#define XILINX_DEFLT_ACTIVE_CH 0
+
+#define MAX_XILINX_TX_DMA_SIZE 0xFFFF
+
+#define MIN_WP_PRI_MTU 128
+#define DEFAULT_WP_PRI_MTU 1500
+
+
+#define MAX_WP_PRI_MTU 8188
+
+
+#define MAX_DATA_SIZE 2000
+struct sdla_hdlc_api{
+ unsigned int cmd;
+ unsigned short len;
+ unsigned char bar;
+ unsigned short offset;
+ unsigned char data[MAX_DATA_SIZE];
+};
+
+#pragma pack(1)
+typedef struct {
+ unsigned char error_flag;
+ unsigned short time_stamp;
+ unsigned char reserved[13];
+} api_rx_hdr_t;
+
+typedef struct {
+ api_rx_hdr_t api_rx_hdr;
+ unsigned char data[1];
+} api_rx_element_t;
+
+typedef struct {
+ unsigned char attr;
+ unsigned char misc_Tx_bits;
+ unsigned char reserved[14];
+} api_tx_hdr_t;
+
+typedef struct {
+ api_tx_hdr_t api_tx_hdr;
+ unsigned char data[1];
+} api_tx_element_t;
+#pragma pack()
+
+#undef wan_udphdr_data
+#define wan_udphdr_data wan_udphdr_u.aft.data
+
+
+
+
+#define PMC_CONTROL_REG 0x00
+
+
+#define PMC_RESET_BIT 0
+
+
+#define PMC_CLOCK_SELECT 1
+
+#define LED_CONTROL_REG 0x01
+
+#define JP8_VALUE 0x02
+#define JP7_VALUE 0x01
+#define SW0_VALUE 0x04
+#define SW1_VALUE 0x08
+
+
+#define SECURITY_CPLD_REG 0x09
+
+#define SECURITY_CPLD_MASK 0x03
+#define SECURITY_CPLD_SHIFT 0x02
+
+#define SECURITY_1LINE_UNCH 0x00
+#define SECURITY_1LINE_CH 0x01
+#define SECURITY_2LINE_UNCH 0x02
+#define SECURITY_2LINE_CH 0x03
+
+
+
+#define WRITE_DEF_SECTOR_DSBL 0x01
+#define FRONT_END_TYPE_MASK 0x38
+
+#define BIT_DEV_ADDR_CLEAR 0x600
+#define BIT_DEV_ADDR_CPLD 0x200
+
+#define MEMORY_TYPE_SRAM 0x00
+#define MEMORY_TYPE_FLASH 0x01
+#define MASK_MEMORY_TYPE_SRAM 0x10
+#define MASK_MEMORY_TYPE_FLASH 0x20
+
+#define BIT_A18_SECTOR_SA4_SA7 0x20
+#define USER_SECTOR_START_ADDR 0x40000
+
+#define MAX_TRACE_QUEUE 100
+
+#define MAX_TRACE_BUFFER (MAX_LGTH_UDP_MGNT_PKT - \
+ sizeof(iphdr_t) - \
+ sizeof(udphdr_t) - \
+ sizeof(wan_mgmt_t) - \
+ sizeof(wan_trace_info_t) - \
+ sizeof(wan_cmd_t))
+
+
+enum {
+ ROUTER_UP_TIME = 0x50,
+ ENABLE_TRACING,
+ DISABLE_TRACING,
+ GET_TRACE_INFO,
+ READ_CODE_VERSION,
+ FLUSH_OPERATIONAL_STATS,
+ OPERATIONAL_STATS,
+ READ_OPERATIONAL_STATS,
+ READ_CONFIGURATION,
+ COMMS_ERROR_STATS_STRUCT,
+ AFT_LINK_STATUS
+};
+
+#define UDPMGMT_SIGNATURE "AFTPIPEA"
+
+
+typedef struct {
+ unsigned char flag ;
+ unsigned short length ;
+ unsigned char rsrv0[2] ;
+ unsigned char attr ;
+ unsigned short tmstamp ;
+ unsigned char rsrv1[4] ;
+ unsigned long offset ;
+}aft_trc_el_t;
+
+
+typedef struct wp_rx_element
+{
+ unsigned long dma_addr;
+ unsigned int reg;
+ unsigned int align;
+ unsigned char pkt_error;
+}wp_rx_element_t;
+
+
+#if defined(_KERNEL)
+
+static __inline unsigned short xilinx_valid_mtu(unsigned short mtu)
+{
+ if (mtu <= 128){
+ return 128;
+ }else if (mtu <= 256){
+ return 256;
+ }else if (mtu <= 512){
+ return 512;
+ }else if (mtu <= 1024){
+ return 1024;
+ }else if (mtu <= 2048){
+ return 2048;
+ }else if (mtu <= 4096){
+ return 4096;
+ }else if (mtu <= 8188){
+ return 8188;
+ }else{
+ return 0;
+ }
+}
+
+static __inline unsigned short xilinx_dma_buf_bits(unsigned short dma_bufs)
+{
+ if (dma_bufs < 2){
+ return 0;
+ }else if (dma_bufs < 3){
+ return 1;
+ }else if (dma_bufs < 5){
+ return 2;
+ }else if (dma_bufs < 9){
+ return 3;
+ }else if (dma_bufs < 17){
+ return 4;
+ }else{
+ return 0;
+ }
+}
+
+#define AFT_TX_TIMEOUT 25
+#define AFT_RX_TIMEOUT 10
+#define AFT_MAX_WTD_TIMEOUT 250
+
+static __inline void aft_reset_rx_watchdog(sdla_t *card)
+{
+ sdla_bus_write_4(card->hw,AFT_TE3_RX_WDT_CTRL_REG,0);
+}
+
+static __inline void aft_enable_rx_watchdog(sdla_t *card, unsigned char timeout)
+{
+ aft_reset_rx_watchdog(card);
+ sdla_bus_write_4(card->hw,AFT_TE3_RX_WDT_CTRL_REG,timeout);
+}
+
+static __inline void aft_reset_tx_watchdog(sdla_t *card)
+{
+ sdla_bus_write_4(card->hw,AFT_TE3_TX_WDT_CTRL_REG,0);
+}
+
+static __inline void aft_enable_tx_watchdog(sdla_t *card, unsigned char timeout)
+{
+ aft_reset_tx_watchdog(card);
+ sdla_bus_write_4(card->hw,AFT_TE3_TX_WDT_CTRL_REG,timeout);
+}
+
+#endif
+
+#endif
diff --git a/sys/dev/pci/if_sandrv.c b/sys/dev/pci/if_sandrv.c
new file mode 100644
index 00000000000..b5ad8cd02f4
--- /dev/null
+++ b/sys/dev/pci/if_sandrv.c
@@ -0,0 +1,1584 @@
+/*-
+ * Copyright (c) 2001-2004 Sangoma Technologies (SAN)
+ * All rights reserved. www.sangoma.com
+ *
+ * This code is written by Alex Feldman <al.feldman@sangoma.com> for SAN.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sangoma Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SANGOMA TECHNOLOGIES AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define __SDLA_HW_LEVEL
+#define __SDLADRV__
+
+/*
+****************************************************************************
+**** For Debug purpose (only OpenBSD) ****
+****************************************************************************
+*/
+
+/***************************************************************************
+**** I N C L U D E F I L E S ****
+***************************************************************************/
+
+# include <sys/types.h>
+# include <sys/param.h>
+# include <sys/systm.h>
+# include <sys/syslog.h>
+# include <sys/malloc.h>
+# include <sys/kernel.h>
+
+# include <dev/pci/pcireg.h>
+# include <dev/pci/pcivar.h>
+# include <dev/pci/if_san_front_end.h>
+# include <dev/pci/if_sandrv.h>
+
+/***************************************************************************
+**** M A C R O S / D E F I N E S ****
+***************************************************************************/
+
+#define EXEC_DELAY 20 /* shared memory access delay, mks */
+# define EXEC_TIMEOUT (hz*2)
+#define MAX_NLOOPS (EXEC_DELAY*2000)
+ /* timeout used if jiffies are stopped
+ ** EXEC_DELAY=20
+ ** EXEC_TIMEOUT=EXEC_DELAY*2000 = 40000
+ ** 40000 ~= 80 jiffies = EXEC_TIMEOUT */
+
+#define EXEC_HZ_DIVISOR 8/10
+ /* We don't want to wait a full second on sdla_exec
+ ** timeout, thus use HZ * EXEC_HZ_DIVISOR to get
+ ** the number of jiffies we would like to wait */
+
+#define IS_SUPPORTED_ADAPTER(hw) ((hw)->type == SDLA_AFT)
+
+#define SDLA_CTYPE_NAME(type) \
+ ((type) == SDLA_AFT) ? "AFT" : "Unknown"
+
+#define IS_AFT(hw) (hw->type == SDLA_AFT)
+
+/* Definitions for identifying and finding S514 PCI adapters */
+#define V3_VENDOR_ID 0x11B0 /* V3 vendor ID number */
+#define V3_DEVICE_ID 0x0002 /* V3 device ID number */
+#define SANGOMA_SUBSYS_VENDOR 0x4753 /* ID for Sangoma */
+
+/* Definition for identifying and finding XILINX PCI adapters */
+#define SANGOMA_PCI_VENDOR 0x1923 /* Old value -> 0x11B0 */
+#define SANGOMA_PCI_VENDOR_OLD 0x10EE /* Old value -> 0x11B0 */
+#define SANGOMA_PCI_DEVICE 0x0300 /* Old value -> 0x0200 */
+
+#define A101_1TE1_SUBSYS_VENDOR 0xA010 /* A101 with T1/E1 1 line */
+#define A101_2TE1_SUBSYS_VENDOR 0xA011 /* A101 with T1/E1 2 lines */
+#define A105_T3_SUBSYS_VENDOR 0xA020 /* A102 with T3 */
+
+/* Read PCI SUBVENDOR ID */
+#define PCI_SUBVENDOR_MASK 0xFFFF
+#define PCI_SUBVENDOR(pa) (pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG) & PCI_SUBVENDOR_MASK)
+#define PCI_DEVICE_MASK 0xFFFF0000
+#define PCI_DEVICE(id) ((id & PCI_DEVICE_MASK ) >> 16)
+
+/* Status values */
+#define SDLA_MEM_RESERVED 0x0001
+#define SDLA_MEM_MAPPED 0x0002
+#define SDLA_IO_MAPPED 0x0004
+#define SDLA_PCI_ENABLE 0x0008
+
+struct san_softc
+{
+ struct device dev;
+ struct pci_attach_args pa;
+};
+
+typedef struct sdla_hw_probe {
+ int used;
+ unsigned char hw_info[100];
+ LIST_ENTRY(sdla_hw_probe) next;
+} sdla_hw_probe_t;
+
+/*
+ * This structure keeps common parameters per physical card.
+ */
+typedef struct sdlahw_card {
+ int used;
+ unsigned int type; /* S50x/S514/ADSL/XILINX */
+ unsigned int atype; /* SubVendor ID */
+ unsigned char core_id; /* SubSystem ID [0..7] */
+ unsigned char core_rev; /* SubSystem ID [8..15] */
+ unsigned char pci_extra_ver;
+ unsigned int slot_no;
+ unsigned int bus_no;
+ bus_space_tag_t memt;
+ struct pci_attach_args pa; /* PCI config header info */
+ pci_intr_handle_t ih;
+ LIST_ENTRY(sdlahw_card) next;
+} sdlahw_card_t;
+
+/*----------------------------------------------------------------------------
+ * Adapter hardware configuration. Pointer to this structure is passed to all
+ * APIs.
+ */
+typedef struct sdlahw
+{
+ int used;
+ unsigned magic;
+ char devname[20];
+ u_int16_t status;
+ int irq; /* interrupt request level */
+ unsigned int cpu_no; /* PCI CPU Number */
+ char auto_pci_cfg; /* Auto PCI configuration */
+ bus_addr_t mem_base_addr;
+ bus_space_handle_t dpmbase; /* dual-port memory base */
+ unsigned dpmsize; /* dual-port memory size */
+ unsigned long memory; /* memory size */
+
+ unsigned reserved[5];
+ unsigned char hw_info[100];
+
+ u_int16_t configured;
+ void *arg; /* card structure */
+ sdla_hw_probe_t* hwprobe;
+ sdlahw_card_t* hwcard;
+ LIST_ENTRY(sdlahw) next;
+} sdlahw_t;
+
+/****** Function Prototypes *************************************************/
+/* Entry Point for Low-Level function */
+int sdladrv_init(void);
+int sdladrv_exit(void);
+
+static int sdla_pci_probe(int, struct pci_attach_args*);
+
+/* PCI bus interface function */
+static int sdla_pci_write_config_word(void*, int, u_int16_t);
+static int sdla_pci_write_config_dword(void*, int, u_int32_t);
+static int sdla_pci_read_config_byte(void*, int, u_int8_t*);
+static int sdla_pci_read_config_word(void*, int, u_int16_t*);
+static int sdla_pci_read_config_dword(void*, int, u_int32_t*);
+
+static int sdla_detect (sdlahw_t* hw);
+static int sdla_detect_aft(sdlahw_t* hw);
+static int sdla_exec (sdlahw_t* hw, unsigned long offset);
+static void sdla_peek_by_4 (sdlahw_t*, unsigned long, void*, unsigned int);
+static void sdla_poke_by_4 (sdlahw_t*, unsigned long, void*, unsigned int);
+
+static sdlahw_card_t* sdla_card_register(u_int16_t atype, int slot_no, int bus_no);
+#if 0
+static int sdla_card_unregister (unsigned char hw_type, int slot_no, int bus_no, int ioport);
+#endif
+static sdlahw_card_t* sdla_card_search(u_int16_t atype, int slot_no, int bus_no);
+
+static sdlahw_t* sdla_hw_register(sdlahw_card_t* card, int cpu_no, int irq, void*);
+#if 0
+static int sdla_hw_unregister(sdlahw_card_t* card, int cpu_no);
+#endif
+static sdlahw_t* sdla_hw_search(u_int16_t atype, int slot_no, int bus_no, int cpu_no);
+
+static sdlahw_t* sdla_aft_hw_select (sdlahw_card_t* card, int cpu_no, int irq, struct pci_attach_args* pa);
+static void sdla_save_hw_probe (sdlahw_t* hw, int port);
+
+
+/* SDLA PCI device relative entry point */
+int san_match __P((struct device*, void*, void*));
+void san_attach __P((struct device*, struct device*, void*));
+
+/****** Global Data *********************************************************/
+
+struct cfdriver san_cd = {
+ NULL, "san", DV_IFNET
+};
+
+struct cfattach san_ca = {
+ sizeof(struct san_softc), san_match, san_attach
+};
+
+extern int ticks;
+
+/* SDLA ISA/PCI varibles */
+static int Sangoma_cards_no = 0;
+static int Sangoma_devices_no = 0;
+static int Sangoma_PCI_cards_no = 0;
+
+/* private data */
+char *san_drvname = "san";
+
+/* Array of already initialized PCI slots */
+static int pci_slot_ar[MAX_S514_CARDS];
+
+LIST_HEAD(, sdlahw_card) sdlahw_card_head =
+ LIST_HEAD_INITIALIZER(sdlahw_card_head);
+LIST_HEAD(, sdlahw) sdlahw_head =
+ LIST_HEAD_INITIALIZER(sdlahw_head);
+LIST_HEAD(, sdla_hw_probe) sdlahw_probe_head =
+ LIST_HEAD_INITIALIZER(sdlahw_probe_head);
+static sdla_hw_type_cnt_t sdla_adapter_cnt;
+
+
+/***************************************************************************/
+
+/******* PCI Device Driver Entry Points ********************************/
+int san_match(parent, match, aux)
+ struct device* parent;
+ void* match, *aux;
+{
+ struct pci_attach_args* pa = aux;
+ u_int16_t vendor_id = PCI_VENDOR(pa->pa_id);
+ u_int16_t device_id = PCI_DEVICE(pa->pa_id);
+
+ if (!(vendor_id == SANGOMA_PCI_VENDOR && device_id == SANGOMA_PCI_DEVICE) ||
+ (vendor_id == SANGOMA_PCI_VENDOR_OLD && device_id == SANGOMA_PCI_DEVICE)){
+ return 0;
+ }
+ return 1;
+}
+
+#define PCI_CBIO 0x10
+void san_attach(parent, self, aux)
+ struct device *parent, *self;
+ void* aux;
+{
+ struct pci_attach_args* pa = aux;
+ u_int16_t vendor_id = PCI_VENDOR(pa->pa_id);
+ u_int16_t subvendor_id = PCI_SUBVENDOR(pa);
+ int atype = 0x00;
+
+ atype = PCI_PRODUCT(pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG));
+ switch(vendor_id){
+ case SANGOMA_PCI_VENDOR_OLD:
+ case SANGOMA_PCI_VENDOR:
+ switch(subvendor_id){
+ case A101_1TE1_SUBSYS_VENDOR:
+ atype = A101_ADPTR_1TE1;
+ break;
+ case A101_2TE1_SUBSYS_VENDOR:
+ atype = A101_ADPTR_2TE1;
+ break;
+ default:
+ return;
+ }
+ break;
+ default:
+ return;
+ }
+
+ if (sdla_pci_probe(atype, pa)){
+ printf(": PCI probe FAILED!\n");
+ return;
+ }
+
+#if defined(DEBUG)
+ switch(PCI_VENDOR(pa->pa_id)){
+ case V3_VENDOR_ID:
+ switch(atype){
+ case S5141_ADPTR_1_CPU_SERIAL:
+ log(LOG_INFO, "%s: Sangoma S5141/FT1 (Single CPU) adapter\n",
+ self->dv_xname);
+ break;
+ case S5142_ADPTR_2_CPU_SERIAL:
+ log(LOG_INFO, "%s: Sangoma S5142 (Dual CPU) adapter\n",
+ self->dv_xname);
+ break;
+ case S5143_ADPTR_1_CPU_FT1:
+ log(LOG_INFO, "%s: Sangoma S5143 (Single CPU) FT1 adapter\n",
+ self->dv_xname);
+ break;
+ case S5144_ADPTR_1_CPU_T1E1:
+ case S5148_ADPTR_1_CPU_T1E1:
+ log(LOG_INFO, "%s: Sangoma S5144 (Single CPU) T1/E1 adapter\n",
+ self->dv_xname);
+ break;
+ case S5145_ADPTR_1_CPU_56K:
+ log(LOG_INFO, "%s: Sangoma S5145 (Single CPU) 56K adapter\n",
+ self->dv_xname);
+ break;
+ case S5147_ADPTR_2_CPU_T1E1:
+ log(LOG_INFO, "%s: Sangoma S5147 (Dual CPU) T1/E1 adapter\n",
+ self->dv_xname);
+ break;
+ }
+ break;
+
+ case PCI_VENDOR_ID_GSI:
+ log(LOG_INFO, "%s: Sangoma S518 ADSL adapter\n",
+ self->dv_xname);
+ break;
+ case SANGOMA_PCI_VENDOR_OLD:
+ switch(atype){
+ case A101_ADPTR_1TE1:
+ log(LOG_INFO, "%s: Sangoma AFT (1 channel) T1/E1 adapter\n",
+ self->dv_xname);
+ break;
+ case A101_ADPTR_2TE1:
+ log(LOG_INFO, "%s: Sangoma AFT (2 channels) T1/E1 adapter\n",
+ self->dv_xname);
+ break;
+ }
+ break;
+ }
+#endif
+ return;
+}
+
+/*==========================================================================
+ * Module init point.
+ */
+int sdladrv_init(void)
+{
+ int volatile i=0;
+
+ /* Initialize the PCI Card array, which
+ * will store flags, used to mark
+ * card initialization state */
+ for (i=0; i<MAX_S514_CARDS; i++)
+ pci_slot_ar[i] = 0xFF;
+
+ memset(&sdla_adapter_cnt,0,sizeof(sdla_hw_type_cnt_t));
+
+ return 0;
+}
+
+/*============================================================================
+ * Module deinit point.
+ * o release all remaining system resources
+ */
+int sdladrv_exit (void)
+{
+#if 0
+ sdla_hw_probe_t *elm_hw_probe;
+ sdlahw_t *elm_hw;
+ sdlahw_card_t *elm_hw_card;
+
+
+ elm_hw = LIST_FIRST(&sdlahw_head);
+ while(elm_hw){
+ sdlahw_t *tmp = elm_hw;
+ elm_hw = LIST_NEXT(elm_hw, next);
+ if (sdla_hw_unregister(tmp->hwcard, tmp->cpu_no) == -EBUSY){
+ return -EBUSY;
+ }
+ }
+ LIST_INIT(&sdlahw_head);
+
+ elm_hw_card = LIST_FIRST(&sdlahw_card_head);
+ while(elm_hw_card){
+ sdlahw_card_t *tmp = elm_hw_card;
+ elm_hw_card = LIST_NEXT(elm_hw_card, next);
+ if (sdla_card_unregister(tmp->hw_type,
+ tmp->slot_no,
+ tmp->bus_no,
+ tmp->ioport) == -EBUSY){
+ return -EBUSY;
+ }
+ }
+ LIST_INIT(&sdlahw_card_head);
+
+ elm_hw_probe = LIST_FIRST(&sdlahw_probe_head);
+ while(elm_hw_probe){
+ sdla_hw_probe_t *tmp = elm_hw_probe;
+ elm_hw_probe = LIST_NEXT(elm_hw_probe, next);
+ if (tmp->used){
+ log(LOG_INFO, "sdladrv: HW probe info is in used (%s)\n",
+ elm_hw_probe->hw_info);
+ return -EBUSY;
+ }
+ LIST_REMOVE(tmp, next);
+ free(tmp, M_DEVBUF);
+ }
+#endif
+ return 0;
+}
+
+/*
+*****************************************************************************
+*****************************************************************************
+G*** S A N G O M A H A R D W A R E P R O B E *****
+*****************************************************************************
+*****************************************************************************
+*/
+/*
+*****************************************************************************
+** sdla_save_hw_probe
+*****************************************************************************
+*/
+static void
+sdla_save_hw_probe (sdlahw_t* hw, int port)
+{
+ sdla_hw_probe_t *tmp_hw_probe;
+
+ tmp_hw_probe = malloc(sizeof(sdla_hw_probe_t), M_DEVBUF, M_NOWAIT);
+ if (!tmp_hw_probe)
+ return;
+
+ memset(tmp_hw_probe,0,sizeof(sdla_hw_probe_t));
+
+ /*sprintf(tmp_hw_probe->hw_info,*/
+ snprintf(tmp_hw_probe->hw_info, sizeof(tmp_hw_probe->hw_info),
+ "%s : SLOT=%d : BUS=%d : IRQ=%d : CPU=%c : PORT=%s",
+ SDLA_ADPTR_DECODE(hw->hwcard->atype),
+ hw->hwcard->slot_no,
+ hw->hwcard->bus_no,
+ hw->irq,
+ SDLA_GET_CPU(hw->cpu_no),
+ "PRI");
+
+ hw->hwprobe = tmp_hw_probe;
+ tmp_hw_probe->used++;
+ LIST_INSERT_HEAD(&sdlahw_probe_head, tmp_hw_probe, next);
+}
+
+
+/*
+*****************************************************************************
+** sdla_hw_select
+*****************************************************************************
+*/
+static sdlahw_t* sdla_aft_hw_select (sdlahw_card_t* hwcard, int cpu_no, int irq, struct pci_attach_args* pa)
+{
+ sdlahw_t* hw=NULL;
+ int number_of_cards = 0;
+
+ hwcard->type = SDLA_AFT;
+ switch(hwcard->atype){
+ case A101_ADPTR_1TE1:
+ hw = sdla_hw_register(hwcard, cpu_no, irq, pa);
+ sdla_save_hw_probe(hw, 0);
+ number_of_cards += 1;
+#if defined(DEBUG)
+ log(LOG_INFO, "%s: %s T1/E1 card found (%s rev.%d), cpu(s) 1, bus #%d, slot #%d, irq #%d\n",
+ san_drvname,
+ SDLA_ADPTR_DECODE(hwcard->atype),
+ AFT_CORE_ID_DECODE(hwcard->core_id),
+ hwcard->core_rev,
+ hwcard->bus_no, hwcard->slot_no, irq);
+#endif
+ break;
+
+ case A101_ADPTR_2TE1:
+ hw = sdla_hw_register(hwcard, cpu_no, irq, pa);
+ sdla_save_hw_probe(hw, 0);
+ number_of_cards += 1;
+#if defined(DEBUG)
+ log(LOG_INFO, "%s: %s T1/E1 card found (%s rev.%d), cpu(s) 2, bus #%d, slot #%d, irq #%d\n",
+ san_drvname,
+ SDLA_ADPTR_DECODE(hwcard->atype),
+ AFT_CORE_ID_DECODE(hwcard->core_id),
+ hwcard->core_rev,
+ hwcard->bus_no, hwcard->slot_no, irq);
+#endif
+ break;
+
+ case A105_ADPTR_1_CHN_T3E3:
+
+ hw = sdla_hw_register(hwcard, cpu_no, irq, pa);
+ sdla_save_hw_probe(hw, 0);
+ number_of_cards += 1;
+#if defined(DEBUG)
+ log(LOG_INFO, "%s: %s T3/E3 card found, cpu(s) 1, bus #%d, slot #%d, irq #%d\n",
+ san_drvname,
+ SDLA_ADPTR_DECODE(hwcard->atype),
+ hwcard->bus_no,
+ hwcard->slot_no,
+ irq);
+#endif
+ break;
+
+
+ default:
+ log(LOG_INFO,
+ "%s: Unknown adapter %04X (bus #%d, slot #%d, irq #%d)!\n",
+ san_drvname, hwcard->atype, hwcard->bus_no, hwcard->slot_no, irq);
+
+ break;
+ }
+
+ return hw;
+}
+
+
+static int sdla_pci_probe(int atype, struct pci_attach_args* pa)
+{
+ sdlahw_card_t* hwcard;
+ sdlahw_t* hw;
+ /*sdladev_t* dev = NULL;*/
+ int dual_cpu = 0;
+ int bus, slot, cpu = SDLA_CPU_A;
+ u_int16_t vendor_id, subvendor_id, device_id;
+ u_int8_t irq;
+ pci_intr_handle_t ih;
+ const char* intrstr = NULL;
+
+ bus = pa->pa_bus;
+ slot = pa->pa_device;
+ vendor_id = PCI_VENDOR(pa->pa_id);
+ subvendor_id = PCI_SUBVENDOR(pa);
+ device_id = PCI_DEVICE(pa->pa_id);
+ irq = (u_int8_t)pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_INTLINE);
+
+ /* Map and establish the interrupt */
+ if (pci_intr_map(pa,&ih)){
+ printf(": couldn't map interrupt\n");
+ return -EINVAL;
+ }
+ intrstr = pci_intr_string(pa->pa_pc, ih);
+ if (intrstr != NULL){
+ printf(" %s\n", intrstr);
+ }
+ Sangoma_cards_no ++;
+reg_new_card:
+ Sangoma_PCI_cards_no ++;
+ hwcard = sdla_card_register(atype, slot, bus);
+ if (hwcard == NULL){
+ return -EINVAL;
+ }
+ hwcard->memt = pa->pa_memt;
+ hwcard->ih = ih;
+ hwcard->pa = *pa;
+ /* Increment number of available Sangoma devices */
+ Sangoma_devices_no ++;
+ switch(atype){
+ case A101_ADPTR_1TE1:
+ case A101_ADPTR_2TE1:
+ hw = sdla_aft_hw_select(hwcard, cpu, irq, pa);
+ sdla_adapter_cnt.AFT_adapters++;
+ if (atype == A101_ADPTR_2TE1) dual_cpu = 1;
+ break;
+
+ }
+
+ if (hw == NULL) return -EINVAL;
+ if (san_dev_attach(hw, hw->devname)){
+ return -EINVAL;
+ }
+ hw->used++;
+
+ if (dual_cpu && cpu == SDLA_CPU_A){
+ cpu = SDLA_CPU_B;
+ goto reg_new_card;
+ }
+
+ return 0;
+}
+
+int sdla_intr_establish(void *phw, int(*intr_func)(void*), void* intr_arg)
+{
+ sdlahw_t *hw = (sdlahw_t*)phw;
+ sdlahw_card_t *hwcard;
+
+ WAN_ASSERT(hw == NULL);
+ hwcard = hw->hwcard;
+ if (pci_intr_establish(
+ hwcard->pa.pa_pc,
+ hwcard->ih,
+ IPL_NET,
+ intr_func,
+ intr_arg,
+ "san") == NULL){
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int sdla_intr_disestablish(void *phw)
+{
+ sdlahw_t *hw = (sdlahw_t*)phw;
+
+ log(LOG_INFO, "%d: Disestablish interrupt is not defined!\n",
+ hw->devname);
+ return -EINVAL;
+}
+
+/*
+*****************************************************************************
+** sdla_get_hw_devices
+*****************************************************************************
+*/
+int sdla_get_hw_devices (void)
+{
+ return Sangoma_devices_no;
+}
+
+/*
+*****************************************************************************
+** sdla_get_hw_adptr_cnt
+*****************************************************************************
+*/
+void *sdla_get_hw_adptr_cnt (void)
+{
+ return &sdla_adapter_cnt;
+}
+
+/*
+*****************************************************************************
+** sdla_card_register
+*****************************************************************************
+*/
+static sdlahw_card_t*
+sdla_card_register(u_int16_t atype, int slot_no, int bus_no)
+{
+ sdlahw_card_t *new_hwcard, *last_hwcard;
+
+ new_hwcard = sdla_card_search(atype, slot_no, bus_no);
+ if (new_hwcard){
+ return new_hwcard;
+ }
+ new_hwcard = malloc(sizeof(sdlahw_card_t), M_DEVBUF, M_NOWAIT);
+ if (!new_hwcard){
+ return NULL;
+ }
+
+ memset(new_hwcard,0,sizeof(sdlahw_card_t));
+
+ new_hwcard->atype = atype;
+ new_hwcard->slot_no = slot_no;
+ new_hwcard->bus_no = bus_no;
+
+ if (LIST_EMPTY(&sdlahw_card_head)){
+ /* Initialize SAN HW parameters */
+ sdladrv_init();
+ }
+ LIST_FOREACH(last_hwcard, &sdlahw_card_head, next){
+ if (!LIST_NEXT(last_hwcard, next)){
+ break;
+ }
+ }
+ if (last_hwcard){
+ LIST_INSERT_AFTER(last_hwcard, new_hwcard, next);
+ }else{
+ LIST_INSERT_HEAD(&sdlahw_card_head, new_hwcard, next);
+ }
+ return new_hwcard;
+}
+
+/*
+*****************************************************************************
+** sdla_card_unregister
+*****************************************************************************
+*/
+#if 0
+static int
+sdla_card_unregister (u_int16_t atype, int slot_no, int bus_no, int ioport)
+{
+ sdlahw_card_t* tmp_card;
+
+ LIST_FOREACH(tmp_card, &sdlahw_card_head, next){
+ if (tmp_card->atype != atype){
+ continue;
+ }
+ if (tmp_card->slot_no == slot_no &&
+ tmp_card->bus_no == bus_no){
+ break;
+ }
+ }
+ if (tmp_card == NULL){
+ log(LOG_INFO, "Error: Card didn't find %04X card (slot=%d, bus=%d)\n",
+ atype, slot_no, bus_no);
+ return -EFAULT;
+ }
+ if (tmp_card->used){
+ log(LOG_INFO, "Error: Card is still in used (slot=%d,bus=%d,used=%d)\n",
+ slot_no, bus_no, tmp_card->used);
+ return -EBUSY;
+ }
+ LIST_REMOVE(tmp_card, next);
+ free(tmp_card, M_DEVBUF);
+ return 0;
+}
+#endif
+/*
+*****************************************************************************
+** sdla_card_search
+*****************************************************************************
+*/
+static sdlahw_card_t*
+sdla_card_search(u_int16_t atype, int slot_no, int bus_no)
+{
+ sdlahw_card_t* tmp_card;
+
+ LIST_FOREACH(tmp_card, &sdlahw_card_head, next){
+ if (tmp_card->atype != atype){
+ continue;
+ }
+ if (tmp_card->slot_no == slot_no &&
+ tmp_card->bus_no == bus_no){
+ return tmp_card;
+ }
+ }
+ return NULL;
+}
+
+/*
+*****************************************************************************
+** sdla_cpu_register
+*****************************************************************************
+*/
+static sdlahw_t*
+sdla_hw_register(sdlahw_card_t* card, int cpu_no, int irq, void* dev)
+{
+ sdlahw_t *new_hw, *last_hw;
+
+ new_hw = sdla_hw_search(card->atype, card->slot_no, card->bus_no, cpu_no);
+ if (new_hw){
+ return new_hw;
+ }
+ new_hw = malloc(sizeof(sdlahw_t), M_DEVBUF, M_NOWAIT);
+ if (!new_hw)
+ return NULL;
+
+ memset(new_hw,0,sizeof(sdlahw_t));
+
+ new_hw->cpu_no = cpu_no;
+ new_hw->irq = irq;
+ new_hw->hwcard = card;
+#if 0
+ new_hw->dev = dev;
+#endif
+ new_hw->magic = SDLAHW_MAGIC;
+ card->used++;
+
+ LIST_FOREACH(last_hw, &sdlahw_head, next){
+ if (!LIST_NEXT(last_hw, next)){
+ break;
+ }
+ }
+ if (last_hw){
+ LIST_INSERT_AFTER(last_hw, new_hw, next);
+ }else{
+ LIST_INSERT_HEAD(&sdlahw_head, new_hw, next);
+ }
+ return new_hw;
+}
+
+/*
+*****************************************************************************
+** sdla_hw_unregister
+*****************************************************************************
+*/
+#if 0
+static int
+sdla_hw_unregister (sdlahw_card_t* hwcard, int cpu_no)
+{
+ sdlahw_t* tmp_hw;
+ int i;
+
+ LIST_FOREACH(tmp_hw, &sdlahw_head, next){
+ if (tmp_hw->hwcard != hwcard){
+ continue;
+ }
+ if (tmp_hw->cpu_no == cpu_no){
+ break;
+ }
+ }
+ if (tmp_hw == NULL){
+ log(LOG_INFO, "Error: Failed to find device (slot=%d,bus=%d,cpu=%c)\n",
+ hwcard->slot_no, hwcard->bus_no, SDLA_GET_CPU(cpu_no));
+ return -EFAULT;
+ }
+ if (tmp_hw->used){
+ log(LOG_INFO, "Error: Device is still in used (slot=%d,bus=%d,cpu=%c,used=%d)\n",
+ hwcard->slot_no, hwcard->bus_no, SDLA_GET_CPU(cpu_no), hwcard->used);
+ return -EBUSY;
+ }
+
+ tmp_hw->hwprobe = NULL;
+ tmp_hw->hwcard = NULL;
+ hwcard->used--; /* Decrement card usage */
+ LIST_REMOVE(tmp_hw, next);
+ free(tmp_hw, M_DEVBUF);
+ return 0;
+}
+#endif
+/*
+*****************************************************************************
+** sdla_cpu_search
+*****************************************************************************
+*/
+static sdlahw_t*
+sdla_hw_search(u_int16_t atype, int slot_no, int bus_no, int cpu_no)
+{
+ sdlahw_t* tmp_hw;
+
+ LIST_FOREACH(tmp_hw, &sdlahw_head, next){
+ if (tmp_hw->hwcard == NULL){
+ log(LOG_INFO, "Critical Error: sdla_cpu_search: line %d\n", __LINE__);
+ LIST_REMOVE(tmp_hw, next);
+ continue;
+ }
+ if (tmp_hw->hwcard->atype != atype){
+ LIST_REMOVE(tmp_hw, next);
+ continue;
+ }
+ if (tmp_hw->hwcard->slot_no == slot_no &&
+ tmp_hw->hwcard->bus_no == bus_no &&
+ tmp_hw->cpu_no == cpu_no){
+ return tmp_hw;
+ }
+ }
+ return NULL;
+}
+
+
+/*
+*****************************************************************************
+*****************************************************************************
+*** S A N G O M A H A R D W A R E R E G I S T E R *****
+*****************************************************************************
+*****************************************************************************
+*/
+
+/******* Kernel APIs ********************************************************/
+
+/*============================================================================
+ * Set up adapter.
+ * o detect adapter type
+ * o set up adapter shared memory
+ * Return: 0 ok.
+ * < 0 error
+ */
+/* ALEX int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len)*/
+int sdla_setup (void* phw)
+{
+ sdlahw_card_t* hwcard = NULL;
+ sdlahw_t* hw = (sdlahw_t*)phw;
+ int err=0;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ WAN_ASSERT(hw->hwcard == NULL);
+ hwcard = hw->hwcard;
+ switch(hwcard->type){
+ case SDLA_AFT:
+ break;
+
+ default:
+ log(LOG_INFO, "%s: Invalid card type %x\n",
+ hw->devname, hw->hwcard->type);
+ return -EINVAL;
+ }
+
+ hw->dpmsize = SDLA_WINDOWSIZE;
+
+ err = sdla_detect(hw);
+ return err;
+}
+
+
+/*============================================================================
+ * Shut down SDLA: disable shared memory access and interrupts, stop CPU, etc.
+ */
+int sdla_down (void* phw)
+{
+ sdlahw_card_t* card = NULL;
+ sdlahw_t* hw = (sdlahw_t*)phw;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ WAN_ASSERT(hw->hwcard == NULL);
+ card = hw->hwcard;
+ switch (card->type) {
+ case SDLA_AFT:
+ /* free up the allocated virtual memory */
+ if (hw->status & SDLA_MEM_MAPPED){
+ bus_space_unmap(hw->hwcard->memt,
+ hw->dpmbase,
+ XILINX_PCI_MEM_SIZE);
+ hw->status &= ~SDLA_MEM_MAPPED;
+ }
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*============================================================================
+ * Read the hardware interrupt status.
+ */
+int sdla_read_int_stat (void* phw, u_int32_t* int_status)
+{
+ sdlahw_card_t* card = NULL;
+ sdlahw_t* hw = (sdlahw_t*)phw;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ WAN_ASSERT(hw->hwcard == NULL);
+ card = hw->hwcard;
+ switch(card->type){
+ case SDLA_AFT:
+ sdla_pci_read_config_dword(hw, PCI_INT_STATUS, int_status);
+ }
+ return 0;
+}
+
+
+/*============================================================================
+ * Generate an interrupt to adapter's CPU.
+ */
+int sdla_cmd (void* phw, unsigned long offset, wan_mbox_t* mbox)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+ int len = sizeof(wan_cmd_t);
+ int err = 0;
+ u_int8_t value;
+
+ SDLA_MAGIC(hw);
+ len += mbox->wan_data_len;
+
+ sdla_peek(hw, offset, (void*)&value, 1);
+ if (value != 0x00){
+ log(LOG_INFO, "%s: opp flag set on entry to sdla_exec!\n",
+ hw->devname);
+ return 0;
+ }
+ mbox->wan_opp_flag = 0x00;
+ sdla_poke(hw, offset, (void*)mbox, len);
+
+ err = sdla_exec(hw, offset);
+ if (!err){
+ log(LOG_INFO, "%s: Command 0x%02X failed!\n",
+ hw->devname, mbox->wan_command);
+ return WAN_CMD_TIMEOUT;
+ }
+ sdla_peek(hw, offset, (void*)mbox, sizeof(wan_cmd_t));
+ if (mbox->wan_data_len){
+ sdla_peek(hw, offset+offsetof(wan_mbox_t, wan_data),
+ mbox->wan_data, mbox->wan_data_len);
+ }
+
+ return mbox->wan_return_code;
+}
+
+/*============================================================================
+ * Execute Adapter Command.
+ * o Set exec flag.
+ * o Busy-wait until flag is reset.
+ * o Return number of loops made, or 0 if command timed out.
+ */
+static int sdla_exec (sdlahw_t* hw, unsigned long offset)
+{
+ volatile unsigned long tstop;
+ volatile unsigned long nloops;
+ u_int8_t value;
+
+ value = 0x01;
+ sdla_poke(hw, offset, (void*)&value, 1);
+ tstop = ticks + EXEC_TIMEOUT;
+
+ sdla_peek(hw, offset, (void*)&value, 1);
+ for (nloops = 1; value == 0x01; ++ nloops){
+ DELAY(EXEC_DELAY);
+ if (ticks > tstop || nloops > MAX_NLOOPS){
+ log(LOG_INFO, "%s: Timeout %lu ticks (max=%lu) loops %lu (max=%u)\n",
+ hw->devname,
+ (ticks-tstop+EXEC_TIMEOUT),
+ (unsigned long)EXEC_TIMEOUT,
+ nloops,
+ MAX_NLOOPS);
+ return 0; /* time is up! */
+ }
+ sdla_peek(hw, offset, (void*)&value, 1);
+ }
+
+ return nloops;
+}
+
+
+/*============================================================================
+ * Read absolute adapter memory.
+ * Transfer data from adapter's memory to data buffer.
+ *
+ * Note:
+ * Care should be taken when crossing dual-port memory window boundary.
+ * This function is not atomic, so caller must disable interrupt if
+ * interrupt routines are accessing adapter shared memory.
+ */
+int sdla_peek (void* phw, unsigned long addr, void* buf, unsigned len)
+{
+ sdlahw_card_t* card = NULL;
+ sdlahw_t* hw = (sdlahw_t*)phw;
+ int err = 0;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ WAN_ASSERT(hw->hwcard == NULL);
+ card = hw->hwcard;
+ if (addr + len > hw->memory) /* verify arguments */
+ return -EINVAL;
+
+ switch(card->type){
+ case SDLA_AFT:
+ sdla_peek_by_4(hw, addr, buf, len);
+ break;
+
+ default:
+ log(LOG_INFO, "%s: Invalid card type 0x%X\n",
+ __FUNCTION__,card->type);
+ err = -EINVAL;
+ break;
+ }
+ return err;
+}
+
+
+/*============================================================================
+ * Read data from adapter's memory to a data buffer in 4-byte chunks.
+ * Note that we ensure that the SDLA memory address is on a 4-byte boundary
+ * before we begin moving the data in 4-byte chunks.
+*/
+static void
+sdla_peek_by_4 (sdlahw_t* hw, unsigned long offset, void* buf, unsigned int len)
+{
+ /* byte copy data until we get to a 4-byte boundary */
+ while (len && (offset & 0x03)){
+ sdla_bus_read_1(hw, offset++, (u_int8_t*)buf);
+ ((u_int8_t *)buf) ++;
+ len --;
+ }
+
+ /* copy data in 4-byte chunks */
+ while (len >= 4){
+ sdla_bus_read_4(hw, offset, (u_int32_t*)buf);
+ (u_int8_t*)buf += 4;
+ offset += 4;
+ len -= 4;
+ }
+
+ /* byte copy any remaining data */
+ while (len){
+ sdla_bus_read_1(hw, offset++, (u_int8_t*)buf);
+ ((u_int8_t *)buf) ++;
+ len --;
+ }
+}
+
+/*============================================================================
+ * Write Absolute Adapter Memory.
+ * Transfer data from data buffer to adapter's memory.
+ *
+ * Note:
+ * Care should be taken when crossing dual-port memory window boundary.
+ * This function is not atomic, so caller must disable interrupt if
+ * interrupt routines are accessing adapter shared memory.
+ */
+int sdla_poke (void* phw, unsigned long addr, void* buf, unsigned len)
+{
+ sdlahw_card_t* card = NULL;
+ sdlahw_t* hw = (sdlahw_t*)phw;
+ int err = 0;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ WAN_ASSERT(hw->hwcard == NULL);
+ card = hw->hwcard;
+ if (addr + len > hw->memory){ /* verify arguments */
+ return -EINVAL;
+ }
+
+ switch (card->type){
+ case SDLA_AFT:
+ sdla_poke_by_4(hw, addr, buf, len);
+ break;
+
+ default:
+ log(LOG_INFO, "%s: Invalid card type 0x%X\n",
+ __FUNCTION__,card->type);
+ err = -EINVAL;
+ break;
+ }
+ return err;
+}
+
+
+/*============================================================================
+ * Write from a data buffer to adapter's memory in 4-byte chunks.
+ * Note that we ensure that the SDLA memory address is on a 4-byte boundary
+ * before we begin moving the data in 4-byte chunks.
+*/
+static void sdla_poke_by_4 (sdlahw_t* hw, unsigned long offset, void* buf, unsigned int len)
+{
+ /* byte copy data until we get to a 4-byte boundary */
+ while (len && (offset & 0x03)){
+ sdla_bus_write_1(hw, offset++, *(char *)buf);
+ ((char *)buf) ++;
+ len --;
+ }
+
+ /* copy data in 4-byte chunks */
+ while (len >= 4){
+ sdla_bus_write_4(hw, offset, *(unsigned long *)buf);
+ offset += 4;
+ (char*)buf += 4;
+ len -= 4;
+ }
+
+ /* byte copy any remaining data */
+ while (len){
+ sdla_bus_write_1(hw, offset++, *(char *)buf);
+ ((char *)buf) ++;
+ len --;
+ }
+}
+
+int sdla_poke_byte (void* phw, unsigned long offset, u_int8_t value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+
+ SDLA_MAGIC(hw);
+ /* Sangoma ISA card sdla_bus_write_1(hw, offset, value); */
+ sdla_poke(hw, offset, (void*)&value, 1);
+ return 0;
+}
+
+int sdla_set_bit (void* phw, unsigned long offset, u_int8_t value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+ u_int8_t tmp;
+
+ SDLA_MAGIC(hw);
+ /* Sangoma ISA card -> sdla_bus_read_1(hw, offset, &tmp); */
+ sdla_peek(hw, offset, (void*)&tmp, 1);
+ tmp |= value;
+ /* Sangoma ISA card -> sdla_bus_write_1(hw, offset, tmp); */
+ sdla_poke(hw, offset, (void*)&tmp, 1);
+ return 0;
+}
+
+
+int sdla_clear_bit (void* phw, unsigned long offset, u_int8_t value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+ u_int8_t tmp;
+
+ SDLA_MAGIC(hw);
+ /* Sangoma ISA card -> sdla_bus_read_1(hw, offset, &tmp); */
+ sdla_peek(hw, offset, (void*)&tmp, 1);
+ tmp &= ~value;
+ /* Sangoma ISA card -> sdla_bus_write_1(hw, offset, tmp); */
+ sdla_poke(hw, offset, (void*)&tmp, 1);
+ return 0;
+}
+
+
+/****** Hardware-Specific Functions *****************************************/
+
+/*
+*****************************************************************************
+*****************************************************************************
+*** S A N G O M A H A R D W A R E D E T E C T I O N *****
+*****************************************************************************
+*****************************************************************************
+*/
+
+/*============================================================================
+ * Find the AFT HDLC PCI adapter in the PCI bus.
+ * Return the number of AFT adapters found (0 if no adapter found).
+ */
+static int sdla_detect_aft(sdlahw_t* hw)
+{
+ sdlahw_card_t* card;
+ u_int16_t ut_u16;
+
+ WAN_ASSERT(hw == NULL);
+ WAN_ASSERT(hw->hwcard == NULL);
+ card = hw->hwcard;
+ sdla_pci_read_config_dword(hw,
+ (hw->cpu_no == SDLA_CPU_A) ? PCI_IO_BASE_DWORD :
+ PCI_MEM_BASE0_DWORD, (u_int32_t*)&hw->mem_base_addr);
+ if (!hw->mem_base_addr){
+ if(hw->cpu_no == SDLA_CPU_B){
+ printf("%s: No PCI memory allocated for CPU #B\n",
+ hw->devname);
+ }else{
+ printf("%s: No PCI memory allocated to card\n",
+ hw->devname);
+ }
+ return -EINVAL;
+ }
+#if defined(DEBUG)
+ log(LOG_INFO, "%s: AFT PCI memory at 0x%lX\n",
+ hw->devname, (unsigned long)hw->mem_base_addr);
+#endif
+ sdla_pci_read_config_byte(hw, PCI_INTLINE, (u_int8_t*)&hw->irq);
+ if(hw->irq == PCI_IRQ_NOT_ALLOCATED) {
+ printf("%s: IRQ not allocated to AFT adapter\n",
+ hw->devname);
+ return -EINVAL;
+ }
+
+#if defined(DEBUG)
+ log(LOG_INFO, "%s: IRQ %d allocated to the AFT PCI card\n",
+ hw->devname, hw->irq);
+#endif
+
+ hw->memory=XILINX_PCI_MEM_SIZE;
+
+ /* map the physical PCI memory to virtual memory */
+ bus_space_map(hw->hwcard->memt,
+ hw->mem_base_addr,
+ XILINX_PCI_MEM_SIZE,
+ 0,
+ &hw->dpmbase);
+ if (!hw->dpmbase){
+ printf("%s: couldn't map memory\n",
+ hw->devname);
+ return -EINVAL;
+ }
+ hw->status |= SDLA_MEM_MAPPED;
+
+
+ /* Enable master operation on PCI and enable
+ * bar0 memory */
+ sdla_pci_read_config_word(hw, XILINX_PCI_CMD_REG, &ut_u16);
+ ut_u16 |=0x06;
+ sdla_pci_write_config_word(hw, XILINX_PCI_CMD_REG, ut_u16);
+
+ /* Set PCI Latency of 0xFF*/
+ sdla_pci_write_config_dword(hw, XILINX_PCI_LATENCY_REG, XILINX_PCI_LATENCY);
+
+ return 0;
+}
+
+
+/*
+ * ============================================================================
+ * Detect adapter type.
+ */
+static int sdla_detect (sdlahw_t* hw)
+{
+ sdlahw_card_t* card = NULL;
+ int err = 0;
+
+ WAN_ASSERT(hw == NULL);
+ WAN_ASSERT(hw->hwcard == NULL);
+ card = hw->hwcard;
+ switch (card->type){
+ case SDLA_AFT:
+ err = sdla_detect_aft(hw);
+ break;
+ }
+ if (err){
+ sdla_down(hw);
+ }
+ return err;
+}
+
+
+
+
+/*
+*****************************************************************************
+*****************************************************************************
+*** H A R D W A R E C O N F I G U R A T I O N *****
+*****************************************************************************
+*****************************************************************************
+*/
+
+int sdla_is_te1(void* phw)
+{
+ sdlahw_card_t* hwcard = NULL;
+ sdlahw_t* hw = (sdlahw_t*)phw;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ WAN_ASSERT(hw->hwcard == NULL);
+ hwcard = hw->hwcard;
+ switch(hwcard->atype){
+ case S5144_ADPTR_1_CPU_T1E1:
+ case S5147_ADPTR_2_CPU_T1E1:
+ case S5148_ADPTR_1_CPU_T1E1:
+ case A101_ADPTR_1TE1:
+ case A101_ADPTR_2TE1:
+ return 1;
+ }
+ return 0;
+
+
+}
+
+int sdla_check_mismatch(void* phw, unsigned char media)
+{
+ sdlahw_card_t* hwcard = NULL;
+ sdlahw_t* hw = (sdlahw_t*)phw;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ WAN_ASSERT(hw->hwcard == NULL);
+ hwcard = hw->hwcard;
+ if (media == WANOPT_MEDIA_T1 ||
+ media == WANOPT_MEDIA_E1){
+ if (hwcard->atype != S5144_ADPTR_1_CPU_T1E1 &&
+ hwcard->atype != S5147_ADPTR_2_CPU_T1E1 &&
+ hwcard->atype != S5148_ADPTR_1_CPU_T1E1){
+ log(LOG_INFO, "%s: Error: Card type mismatch: User=T1/E1 Actual=%s\n",
+ hw->devname,
+ SDLA_ADPTR_DECODE(hwcard->atype));
+ return -EIO;
+ }
+ hwcard->atype = S5144_ADPTR_1_CPU_T1E1;
+
+ }else if (media == WANOPT_MEDIA_56K){
+ if (hwcard->atype != S5145_ADPTR_1_CPU_56K){
+ log(LOG_INFO, "%s: Error: Card type mismatch: User=56K Actual=%s\n",
+ hw->devname,
+ SDLA_ADPTR_DECODE(hwcard->atype));
+ return -EIO;
+ }
+ }else{
+ if (hwcard->atype == S5145_ADPTR_1_CPU_56K ||
+ hwcard->atype == S5144_ADPTR_1_CPU_T1E1 ||
+ hwcard->atype == S5147_ADPTR_2_CPU_T1E1 ||
+ hwcard->atype == S5148_ADPTR_1_CPU_T1E1){
+ log(LOG_INFO, "%s: Error: Card type mismatch: User=S514(1/2/3) Actual=%s\n",
+ hw->devname,
+ SDLA_ADPTR_DECODE(hwcard->atype));
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+int sdla_getcfg(void* phw, int type, void* value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+ sdlahw_card_t* hwcard;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ WAN_ASSERT(hw->hwcard == NULL);
+ hwcard = hw->hwcard;
+ switch(type){
+ case SDLA_CARDTYPE:
+ *(u_int16_t*)value = hwcard->type;
+ break;
+ case SDLA_MEMBASE:
+ *(bus_space_handle_t*)value = hw->dpmbase;
+ break;
+ case SDLA_MEMEND:
+ *(u_int32_t*)value = ((unsigned long)hw->dpmbase + hw->dpmsize - 1);
+ break;
+ case SDLA_MEMSIZE:
+ *(u_int16_t*)value = hw->dpmsize;
+ break;
+ case SDLA_MEMORY:
+ *(u_int32_t*)value = hw->memory;
+ break;
+ case SDLA_IRQ:
+ *(u_int16_t*)value = hw->irq;
+ break;
+ case SDLA_ADAPTERTYPE:
+ *(u_int16_t*)value = hwcard->atype;
+ break;
+ case SDLA_CPU:
+ *(u_int16_t*)value = hw->cpu_no;
+ break;
+ case SDLA_SLOT:
+ *(u_int16_t*)value = hwcard->slot_no;
+ break;
+ case SDLA_BUS:
+ *(u_int16_t*)value = hwcard->bus_no;
+ break;
+ case SDLA_DMATAG:
+ *(bus_dma_tag_t*)value = hwcard->pa.pa_dmat;
+ break;
+ case SDLA_PCIEXTRAVER:
+ *(u_int8_t*)value = hwcard->pci_extra_ver;
+ break;
+ case SDLA_BASEADDR:
+ *(u_int32_t*)value = hw->mem_base_addr;
+ break;
+ }
+ return 0;
+}
+
+
+int sdla_get_hwcard(void* phw, void** phwcard)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+
+ *phwcard = hw->hwcard;
+ return 0;
+}
+
+
+int sdla_get_hwprobe(void* phw, void** str)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+
+ if (hw->hwprobe){
+ *str = hw->hwprobe->hw_info;
+ }
+ return 0;
+}
+
+/*
+*****************************************************************************
+*****************************************************************************
+*** M I S C E L L A N E O U S *****
+*****************************************************************************
+*****************************************************************************
+*/
+
+int sdla_bus_write_1(void* phw, unsigned int offset, u_int8_t value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ if (!(hw->status & SDLA_MEM_MAPPED)) return 0;
+ bus_space_write_1(hw->hwcard->memt, hw->dpmbase, offset, value);
+ return 0;
+}
+
+int sdla_bus_write_2(void* phw, unsigned int offset, u_int16_t value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ if (!(hw->status & SDLA_MEM_MAPPED)) return 0;
+ bus_space_write_2(hw->hwcard->memt, hw->dpmbase, offset, value);
+ return 0;
+}
+
+int sdla_bus_write_4(void* phw, unsigned int offset, u_int32_t value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ if (!(hw->status & SDLA_MEM_MAPPED)) return 0;
+ bus_space_write_4(hw->hwcard->memt, hw->dpmbase, offset, value);
+ return 0;
+}
+
+int sdla_bus_read_1(void* phw, unsigned int offset, u_int8_t* value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+
+ WAN_ASSERT2(hw == NULL, 0);
+ SDLA_MAGIC(hw);
+ if (!(hw->status & SDLA_MEM_MAPPED)) return 0;
+ *value = bus_space_read_1(hw->hwcard->memt, hw->dpmbase, offset);
+ return 0;
+}
+
+int sdla_bus_read_2(void* phw, unsigned int offset, u_int16_t* value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+
+ WAN_ASSERT2(hw == NULL, 0);
+ SDLA_MAGIC(hw);
+ if (!(hw->status & SDLA_MEM_MAPPED)) return 0;
+ *value = bus_space_read_2(hw->hwcard->memt, hw->dpmbase, offset);
+ return 0;
+}
+
+int sdla_bus_read_4(void* phw, unsigned int offset, u_int32_t* value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+
+ WAN_ASSERT2(hw == NULL, 0);
+ WAN_ASSERT2(hw->dpmbase == 0, 0);
+ SDLA_MAGIC(hw);
+ if (!(hw->status & SDLA_MEM_MAPPED)) return 0;
+ *value = bus_space_read_4(hw->hwcard->memt, hw->dpmbase, offset);
+ return 0;
+}
+
+static int sdla_pci_read_config_dword(void* phw, int reg, u_int32_t* value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+ sdlahw_card_t* hwcard;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ WAN_ASSERT(hw->hwcard == NULL);
+ hwcard = hw->hwcard;
+ *value = pci_conf_read(hwcard->pa.pa_pc, hwcard->pa.pa_tag, reg);
+ return 0;
+}
+
+static int sdla_pci_read_config_word(void* phw, int reg, u_int16_t* value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+ sdlahw_card_t* hwcard;
+ u_int32_t tmp = 0x00;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ WAN_ASSERT(hw->hwcard == NULL);
+ hwcard = hw->hwcard;
+ tmp = pci_conf_read(hwcard->pa.pa_pc, hwcard->pa.pa_tag, reg);
+ *value = (u_int16_t)((tmp >> 16) & 0xFFFF);
+ return 0;
+}
+
+static int sdla_pci_read_config_byte(void* phw, int reg, u_int8_t* value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+ sdlahw_card_t* hwcard;
+ u_int32_t tmp = 0x00;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ WAN_ASSERT(hw->hwcard == NULL);
+ hwcard = hw->hwcard;
+ tmp = pci_conf_read(hwcard->pa.pa_pc, hwcard->pa.pa_tag, reg);
+ *value = (u_int8_t)(tmp & 0xFF);
+ return 0;
+}
+
+static int sdla_pci_write_config_dword(void* phw, int reg, u_int32_t value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+ sdlahw_card_t* card;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ WAN_ASSERT(hw->hwcard == NULL);
+ card = hw->hwcard;
+ pci_conf_write(card->pa.pa_pc, card->pa.pa_tag, reg, value);
+ return 0;
+}
+
+static int sdla_pci_write_config_word(void* phw, int reg, u_int16_t value)
+{
+ sdlahw_t* hw = (sdlahw_t*)phw;
+ sdlahw_card_t* card;
+
+ WAN_ASSERT(hw == NULL);
+ SDLA_MAGIC(hw);
+ WAN_ASSERT(hw->hwcard == NULL);
+ card = hw->hwcard;
+ pci_conf_write(card->pa.pa_pc, card->pa.pa_tag, reg, value);
+ return 0;
+}
+
+
diff --git a/sys/dev/pci/if_sandrv.h b/sys/dev/pci/if_sandrv.h
new file mode 100644
index 00000000000..ff41bc56542
--- /dev/null
+++ b/sys/dev/pci/if_sandrv.h
@@ -0,0 +1,331 @@
+/*-
+ * Copyright (c) 2001-2004 Sangoma Technologies (SAN)
+ * All rights reserved. www.sangoma.com
+ *
+ * This code is written by Alex Feldman <al.feldman@sangoma.com> for SAN.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Sangoma Technologies nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SANGOMA TECHNOLOGIES AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __IF_SANDRV_H
+# define __IF_SANDRV_H
+
+#ifdef __SDLADRV__
+# define EXTERN
+#else
+# define EXTERN extern
+#endif
+
+
+
+#define WAN_MAILBOX_SIZE 16
+#define WAN_MAX_DATA_SIZE 2032
+#pragma pack(1)
+typedef struct {
+ union {
+ struct {
+ unsigned char opp_flag;
+ unsigned char command;
+ unsigned short data_len;
+ unsigned char return_code;
+ } wan_p_cmd;
+ unsigned char mbox[WAN_MAILBOX_SIZE];
+ } wan_cmd_u;
+#define wan_cmd_opp_flag wan_cmd_u.wan_p_cmd.opp_flag
+#define wan_cmd_command wan_cmd_u.wan_p_cmd.command
+#define wan_cmd_data_len wan_cmd_u.wan_p_cmd.data_len
+#define wan_cmd_return_code wan_cmd_u.wan_p_cmd.return_code
+} wan_cmd_t;
+#pragma pack()
+
+/************************************************
+ * GLOBAL DEFINITION FOR SANGOMA MAILBOX *
+ ************************************************/
+#pragma pack(1)
+typedef struct {
+ wan_cmd_t wan_cmd;
+ unsigned char wan_data[WAN_MAX_DATA_SIZE];
+#define wan_opp_flag wan_cmd.wan_cmd_opp_flag
+#define wan_command wan_cmd.wan_cmd_command
+#define wan_data_len wan_cmd.wan_cmd_data_len
+#define wan_return_code wan_cmd.wan_cmd_return_code
+} wan_mbox_t;
+#pragma pack()
+#define WAN_MBOX_INIT(mbox) memset(mbox, 0, sizeof(wan_cmd_t));
+
+
+#if defined(_KERNEL)
+
+/*
+******************************************************************
+** D E F I N E S **
+******************************************************************
+*/
+#define SDLADRV_MAJOR_VER 2
+#define SDLADRV_MINOR_VER 1
+#define SDLA_WINDOWSIZE 0x2000 /* default dual-port memory window size */
+
+/* Adapter types */
+#define SDLA_S508 5080
+#define SDLA_S514 5140
+#define SDLA_ADSL 6000
+#define SDLA_AFT 7000
+
+#define SDLA_PRI_PORT 1
+#define SDLA_SEC_PORT 2
+
+/* Firmware supported version */
+#define SFM_VERSION 2
+#define SFM_SIGNATURE "SFM - Sangoma SDLA Firmware Module"
+
+/* min/max */
+#define SFM_IMAGE_SIZE 0x8000 /* max size of SDLA code image file */
+#define SFM_DESCR_LEN 256 /* max length of description string */
+#define SFM_MAX_SDLA 16 /* max number of compatible adapters */
+
+/* Firmware identification numbers:
+ * 0 .. 999 Test & Diagnostics
+ * 1000 .. 1999 Streaming HDLC
+ * 2000 .. 2999 Bisync
+ * 3000 .. 3999 SDLC
+ * 4000 .. 4999 HDLC
+ * 5000 .. 5999 X.25
+ * 6000 .. 6999 Frame Relay
+ * 7000 .. 7999 PPP
+ * 8000 .. 8999 Cisco HDLC
+ */
+#define SFID_HDLC502 4200
+#define SFID_HDLC508 4800
+#define SFID_CHDLC508 8800
+#define SFID_CHDLC514 8140
+#define SFID_AFT 30000
+
+/* */
+#define SDLA_MEMBASE 0x01
+#define SDLA_MEMEND 0x02
+#define SDLA_MEMSIZE 0x03
+#define SDLA_MEMORY 0x05
+#define SDLA_BASEADDR 0x06
+#define SDLA_DMATAG 0x04
+#define SDLA_IRQ 0x07
+#define SDLA_BUS 0x08
+#define SDLA_CPU 0x0A
+#define SDLA_SLOT 0x0B
+#define SDLA_ADAPTERTYPE 0x0C
+#define SDLA_CARDTYPE 0x0D
+#define SDLA_PCIEXTRAVER 0x0E
+
+/* S514 PCI adapter CPU numbers */
+#define SDLA_MAX_CPUS 2
+#define S514_CPU_A 'A'
+#define S514_CPU_B 'B'
+#define SDLA_CPU_A 1
+#define SDLA_CPU_B 2
+#define SDLA_GET_CPU(cpu_no) (cpu_no==SDLA_CPU_A)?S514_CPU_A:S514_CPU_B
+
+#define AFT_CORE_ID_MASK 0x00FF
+#define AFT_CORE_REV_MASK 0xFF00
+#define AFT_HDLC_CORE_ID 0x00 /* HDLC core */
+#define AFT_ATM_CORE_ID 0x01 /* ATM core */
+#define AFT_SS7_CORE_ID 0x02 /* SS7 core */
+
+#define XILINX_PCI_MEM_SIZE 0x2FF
+#define XILINX_PCI_LATENCY 0x0000FF00
+
+#define XILINX_PCI_CMD_REG 0x04
+#define XILINX_PCI_LATENCY_REG 0x0C
+
+/* Local PCI register offsets */
+#if 0
+#define PCI_VENDOR_ID_WORD 0x00 /* vendor ID */
+#define PCI_DEVICE_ID_WORD 0x02 /* device ID */
+#define PCI_SUBCLASS_ID_BYTE 0x0a /* subclass ID byte */
+#endif
+#define PCI_IO_BASE_DWORD 0x10 /* IO base */
+#define PCI_MEM_BASE0_DWORD 0x14 /* memory base - apperture 0 */
+#define PCI_MEM_BASE1_DWORD 0x18 /* memory base - apperture 1 */
+#if 0
+#define PCI_SUBSYS_VENDOR_WORD 0x2C /* subsystem vendor ID */
+#define PCI_SUBSYS_ID_WORD 0x2E /* subsystem ID */
+#define PCI_INT_LINE_BYTE 0x3C /* interrupt line */
+#define PCI_INT_PIN_BYTE 0x3D /* interrupt pin */
+#endif
+#define PCI_MAP0_DWORD 0x40 /* PCI to local bus address 0 */
+#define PCI_MAP1_DWORD 0x44 /* PCI to local bus address 1 */
+#define PCI_INT_STATUS 0x48 /* interrupt status */
+#define PCI_INT_CONFIG 0x4C /* interrupt configuration */
+
+#define PCI_DEV_SLOT_MASK 0x1F /* mask for slot numbering */
+#define PCI_IRQ_NOT_ALLOCATED 0xFF /* interrupt line for no IRQ */
+/* Local PCI register usage */
+#define PCI_MEMORY_ENABLE 0x00000003 /* enable PCI memory */
+#define PCI_CPU_A_MEM_DISABLE 0x00000002 /* disable CPU A memory */
+#define PCI_CPU_B_MEM_DISABLE 0x00100002 /* disable CPU B memory */
+#define PCI_ENABLE_IRQ_CPU_A 0x005A0004 /* enable IRQ for CPU A */
+#define PCI_ENABLE_IRQ_CPU_B 0x005A0008 /* enable IRQ for CPU B */
+#define PCI_ENABLE_IRQ_DMA0 0x01000000 /* enable IRQ for DMA 0 */
+#define PCI_ENABLE_IRQ_DMA1 0x02000000 /* enable IRQ for DMA 1 */
+#define PCI_DISABLE_IRQ_CPU_A 0x00000004 /* disable IRQ for CPU A */
+#define PCI_DISABLE_IRQ_CPU_B 0x00000008 /* disable IRQ for CPU B */
+#define PCI_DISABLE_IRQ_DMA0 0x01000000 /* disable IRQ for DMA 0 */
+#define PCI_DISABLE_IRQ_DMA1 0x02000000 /* disable IRQ for DMA 1 */
+
+/* Setting for the Interrupt Status register */
+#define IRQ_DMA0 0x01000000 /* IRQ for DMA0 */
+#define IRQ_DMA1 0x02000000 /* IRQ for DMA1 */
+#define IRQ_LOCAL_CPU_A 0x00000004 /* IRQ for CPU A */
+#define IRQ_LOCAL_CPU_B 0x00000008 /* IRQ for CPU B */
+#define IRQ_CPU_A 0x04 /* IRQ for CPU A */
+#define IRQ_CPU_B 0x08 /* IRQ for CPU B */
+
+/* The maximum size of the S514 memory */
+#define MAX_SIZEOF_S514_MEMORY (256 * 1024)
+
+/* S514 control register offsets within the memory address space */
+#define S514_CTRL_REG_BYTE 0x80000
+
+/* S514 adapter control bytes */
+#define S514_CPU_HALT 0x00
+#define S514_CPU_START 0x01
+
+/* The maximum number of S514 adapters supported */
+#define MAX_S514_CARDS 20
+
+#define WAN_CMD_OK 0 /* normal firmware return code */
+#define WAN_CMD_TIMEOUT 0xFF /* firmware command timed out */
+
+/* signature: 'SDLA' reversed */
+#define SDLAHW_MAGIC 0x414C4453L
+
+/*
+******************************************************************
+** M A C R O S **
+******************************************************************
+*/
+#define AFT_CORE_ID_DECODE(core_id) \
+ (core_id == AFT_HDLC_CORE_ID) ? "HDLC" : \
+ (core_id == AFT_ATM_CORE_ID) ? "ATM" : \
+ (core_id == AFT_SS7_CORE_ID) ? "SS7" : \
+ "Unknown"
+#define WAN_ASSERT(val) \
+ if (val){ \
+ log(LOG_INFO, "********** ASSERT FAILED **********\n"); \
+ log(LOG_INFO, "%s:%d - Critical error\n", \
+ __FILE__,__LINE__); \
+ return -EINVAL; \
+ }
+
+#define WAN_ASSERT1(val) \
+ if (val){ \
+ log(LOG_INFO, "********** ASSERT FAILED **********\n"); \
+ log(LOG_INFO, "%s:%d - Critical error\n", \
+ __FILE__,__LINE__); \
+ return; \
+ }
+
+#define WAN_ASSERT2(val, ret) \
+ if (val){ \
+ log(LOG_INFO, "********** ASSERT FAILED **********\n"); \
+ log(LOG_INFO, "%s:%d - Critical error\n", \
+ __FILE__,__LINE__); \
+ return ret; \
+ }
+
+#define SDLA_MAGIC(hw) WAN_ASSERT((hw)->magic != SDLAHW_MAGIC)
+/*
+******************************************************************
+** S T R U C T U R E S **
+******************************************************************
+*/
+
+typedef struct sfm_info /* firmware module information */
+{
+ unsigned short codeid; /* firmware ID */
+ unsigned short version; /* firmaware version number */
+ unsigned short adapter[SFM_MAX_SDLA]; /* compatible adapter types */
+ unsigned long memsize; /* minimum memory size */
+ unsigned short reserved[2]; /* reserved */
+ unsigned short startoffs; /* entry point offset */
+ unsigned short winoffs; /* dual-port memory window offset */
+ unsigned short codeoffs; /* code load offset */
+ unsigned short codesize; /* code size */
+ unsigned short dataoffs; /* configuration data load offset */
+ unsigned short datasize; /* configuration data size */
+} sfm_info_t;
+
+typedef struct sfm /* SDLA firmware file structire */
+{
+ char signature[80]; /* SFM file signature */
+ unsigned short version; /* file format version */
+ unsigned short checksum; /* info + image */
+ unsigned short reserved[6]; /* reserved */
+ char descr[SFM_DESCR_LEN]; /* description string */
+ sfm_info_t info; /* firmware module info */
+ unsigned char image[1]; /* code image (variable size) */
+} sfm_t;
+
+
+typedef struct sdla_hw_type_cnt
+{
+ unsigned char AFT_adapters;
+}sdla_hw_type_cnt_t;
+
+/****** Function Prototypes *************************************************/
+extern int san_dev_attach(void*, u_int8_t*);
+
+/* Hardware interface function */
+extern int sdladrv_init(void);
+extern int sdladrv_exit(void);
+extern int sdla_get_hw_devices(void);
+extern void *sdla_get_hw_adptr_cnt(void);
+
+extern int sdla_setup (void*);
+extern int sdla_down (void*);
+extern int sdla_read_int_stat (void*, u_int32_t*);
+extern int sdla_check_mismatch(void*, unsigned char);
+extern int sdla_cmd (void*, unsigned long, wan_mbox_t*);
+extern int sdla_getcfg(void*, int, void*);
+extern int sdla_bus_write_1(void*, unsigned int, u_int8_t);
+extern int sdla_bus_write_2(void*, unsigned int, u_int16_t);
+extern int sdla_bus_write_4(void*, unsigned int, u_int32_t);
+extern int sdla_bus_read_1(void*, unsigned int, u_int8_t*);
+extern int sdla_bus_read_2(void*, unsigned int, u_int16_t*);
+extern int sdla_bus_read_4(void*, unsigned int, u_int32_t*);
+extern int sdla_peek (void*, unsigned long, void*, unsigned);
+extern int sdla_poke (void*, unsigned long, void*, unsigned);
+extern int sdla_poke_byte (void*, unsigned long, u_int8_t);
+extern int sdla_set_bit (void*, unsigned long, u_int8_t);
+extern int sdla_clear_bit (void*, unsigned long, u_int8_t);
+extern int sdla_intr_establish(void*, int(*intr_func)(void*), void*);
+extern int sdla_intr_disestablish(void*);
+extern int sdla_get_hwprobe(void*, void**);
+extern int sdla_get_hwcard(void*, void**);
+extern int sdla_is_te1(void*);
+
+#endif
+
+#undef EXTERN
+#endif /* __IF_SANDRV_H */