diff options
-rw-r--r-- | sys/dev/pci/if_san_common.c | 401 | ||||
-rw-r--r-- | sys/dev/pci/if_san_common.h | 400 | ||||
-rw-r--r-- | sys/dev/pci/if_san_front_end.h | 217 | ||||
-rw-r--r-- | sys/dev/pci/if_san_obsd.c | 393 | ||||
-rw-r--r-- | sys/dev/pci/if_san_obsd.h | 109 | ||||
-rw-r--r-- | sys/dev/pci/if_san_te1.c | 3987 | ||||
-rw-r--r-- | sys/dev/pci/if_san_te1.h | 987 | ||||
-rw-r--r-- | sys/dev/pci/if_san_xilinx.c | 3535 | ||||
-rw-r--r-- | sys/dev/pci/if_san_xilinx.h | 667 | ||||
-rw-r--r-- | sys/dev/pci/if_sandrv.c | 1584 | ||||
-rw-r--r-- | sys/dev/pci/if_sandrv.h | 331 |
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*)⁡ + 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*)⁡ + 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,®); + + /* 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*)®, INTERFACE_TYPE_T1_E1_BIT); + bit_set((u_int8_t*)®, 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*)®, INTERFACE_TYPE_T1_E1_BIT); + bit_set((u_int8_t*)®, 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,®); + bit_clear((u_int8_t*)®, FRONT_END_RESET_BIT); + sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg); + DELAY(1000); + + bit_set((u_int8_t*)®, 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, ®); + bit_set((u_int8_t*)®, 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*)®, CHIP_RESET_BIT); + + /* Disable ALL chip interrupts */ + bit_clear((u_int8_t*)®, GLOBAL_INTR_ENABLE_BIT); + bit_clear((u_int8_t*)®, ERROR_INTR_ENABLE_BIT); + bit_clear((u_int8_t*)®, 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,®); + bit_set((u_int8_t*)®, 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, ®); + + /* Disable the chip/hdlc reset condition */ + bit_set((u_int8_t*)®, 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*)®, 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*)®); + if (bit_test((u_int8_t*)®, 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*)®, CHIP_RESET_BIT); + sdla_bus_write_4(card->hw,XILINX_CHIP_CFG_REG,reg); + return err; + } + if (bit_test((u_int8_t*)®, 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*)®, 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*)®, GLOBAL_INTR_ENABLE_BIT); + bit_clear((u_int8_t*)®, ERROR_INTR_ENABLE_BIT); + + /* Always enable the front end interrupt */ + bit_set((u_int8_t*)®, 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, ®); + /* Enable the chip/hdlc reset condition */ + reg=0; + bit_set((u_int8_t*)®, 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&=~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&=~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&=~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*)®, HDLC_RX_PROT_DISABLE_BIT); + bit_clear((u_int8_t*)®, HDLC_TX_PROT_DISABLE_BIT); + + bit_set((u_int8_t*)®, 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&=~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*)®, HDLC_RX_PROT_DISABLE_BIT); + bit_clear((u_int8_t*)®, HDLC_TX_PROT_DISABLE_BIT); + + bit_set((u_int8_t*)®, HDLC_TX_CHAN_ENABLE_BIT); + bit_set((u_int8_t*)®, 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&=~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&=~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*)®, 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,®); + if (bit_test((u_int8_t*)®, 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*)®, 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,®); + if (bit_test((u_int8_t*)®, 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, ®); + bit_set((u_int8_t*)®, 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, ®); + + bit_clear((u_int8_t*)®, 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&=~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, ®); + + if (bit_test((u_int8_t*)®,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*)®, 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, ®); + + if (bit_test((u_int8_t*)®, 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*)®, TxDMA_HI_DMA_FRAME_START_BIT); + bit_set((u_int8_t*)®, TxDMA_HI_DMA_FRAME_END_BIT); + + bit_set((u_int8_t*)®, 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, ®); + + 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*)®, 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*)®, 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*)®, 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, ®); + + /* 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, ®); + 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, ®); + + if (bit_test((u_int8_t*)®, 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*)®, FRONT_END_INTR_ENABLE_BIT)){ + if (bit_test((u_int8_t*)®, 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*)®, ERROR_INTR_ENABLE_BIT)){ + if (bit_test((u_int8_t*)®, 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*)®, GLOBAL_INTR_ENABLE_BIT) && + bit_test((u_int8_t*)®, 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, ®); + sdla_bus_read_4(card->hw, + XILINX_DMA_TX_INTR_PENDING_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,®); + bit_set((u_int8_t*)®, 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, ®); + sdla_bus_read_4(card->hw, + XILINX_HDLC_TX_INTR_PENDING_REG, ®); + + /* Enable Global DMA and Error Interrupts */ + + reg=0; + sdla_bus_read_4(card->hw,XILINX_CHIP_CFG_REG,®); + bit_set((u_int8_t*)®, GLOBAL_INTR_ENABLE_BIT); + bit_set((u_int8_t*)®, 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,®); + bit_clear((u_int8_t*)®, GLOBAL_INTR_ENABLE_BIT); + bit_clear((u_int8_t*)®, ERROR_INTR_ENABLE_BIT); + if (event==DEVICE_DOWN){ + bit_clear((u_int8_t*)®, 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,®); + bit_clear((u_int8_t*)®, 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&=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*)®, 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*)®, 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, ®); + if (!bit_test((u_int8_t*)®, 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 */ |