#ifndef XPD_H #define XPD_H /* * Written by Oron Peled * Copyright (C) 2004-2006, Xorcom * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "xdefs.h" #include "xproto.h" #ifdef __KERNEL__ #include #include #include #include #include #ifdef XPP_DEBUGFS #ifndef CONFIG_DEBUG_FS #warning kernel does not include CONFIG_DEBUG_FS, canceling XPP_DEBUGFS support #undef XPP_DEBUGFS #else #include #endif #endif #endif /* __KERNEL__ */ #include #ifdef __KERNEL__ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) /* also added in RHEL kernels with the OpenInfiniband backport: */ #if LINUX_VERSION_CODE != KERNEL_VERSION(2,6,9) || !defined(DEFINE_SPINLOCK) typedef unsigned gfp_t; /* Added in 2.6.14 */ #endif #endif /* * FIXME: Kludge for 2.6.19 * bool is now defined as a proper boolean type (gcc _Bool) * but the command line parsing framework handles it as int. */ #define DEF_PARM_BOOL(name,init,perm,desc) \ int name = init; \ module_param(name, bool, perm); \ MODULE_PARM_DESC(name, desc " [default " #init "]") #define DEF_PARM(type,name,init,perm,desc) \ type name = init; \ module_param(name, type, perm); \ MODULE_PARM_DESC(name, desc " [default " #init "]") #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) /* * Old 2.6 kernels had module_param_array() macro that receive the counter * by value. */ #define DEF_ARRAY(type,name,count,init,desc) \ unsigned int name ## _num_values; \ type name[count] = { [0 ... ((count)-1)] = (init) }; \ module_param_array(name, type, name ## _num_values, 0600); \ MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")") #else #define DEF_ARRAY(type,name,count,init,desc) \ unsigned int name ## _num_values; \ type name[count] = {[0 ... ((count)-1)] = init}; \ module_param_array(name, type, &name ## _num_values, 0600); \ MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")") #endif #endif // __KERNEL__ typedef struct xbus_ops xbus_ops_t; typedef enum xbus_type { FIRMWARE_LOOPBACK = 1, FIRMWARE_XPP = 2, } xbus_type_t; #ifdef __KERNEL__ typedef struct packet_queue { char qname[XPD_NAMELEN]; struct list_head head; unsigned int count; unsigned int worst_count; unsigned int overflows; spinlock_t lock; } packet_queue_t; struct xbus_ops { int (*xframe_send)(xbus_t *xbus, xframe_t *xframe); xframe_t *(*xframe_new)(xbus_t *xbus, gfp_t flags); void (*xframe_free)(xbus_t *xbus, xframe_t *p); }; /* * XBUS statistics counters */ enum { XBUS_N_DESC_REQ, XBUS_N_DEV_DESC_FULL, XBUS_N_DEV_DESC_EMPTY, XBUS_N_TX_XFRAME_PCM, XBUS_N_RX_XFRAME_PCM, XBUS_N_TX_PACK_PCM, XBUS_N_RX_PACK_PCM, XBUS_N_TX_BYTES, XBUS_N_RX_BYTES, XBUS_N_TX_PCM_FRAG, }; #define XBUS_COUNTER(xbus, counter) ((xbus)->counters[XBUS_N_ ## counter]) #define C_(x) [ XBUS_N_ ## x ] = { #x } /* yucky, make an instance so we can size it... */ static struct xbus_counters { char *name; } xbus_counters[] = { C_(DESC_REQ), C_(DEV_DESC_FULL), C_(DEV_DESC_EMPTY), C_(TX_XFRAME_PCM), C_(RX_XFRAME_PCM), C_(TX_PACK_PCM), C_(RX_PACK_PCM), C_(TX_BYTES), C_(RX_BYTES), C_(TX_PCM_FRAG), }; #undef C_ #define XBUS_COUNTER_MAX ARRAY_SIZE(xbus_counters) #define CARD_DESC_MAGIC 0xca9dde5c struct card_desc_struct { struct list_head card_list; u32 magic; xbus_t *xbus; byte rev; /* Revision number */ byte type; /* LSB: 1 - to_phone, 0 - to_line */ byte subtype; xpd_addr_t xpd_addr; xpp_line_t line_status; /* Initial line status (offhook) */ }; #ifdef XPP_DEBUGFS /* definition in xbus-core.c */ struct debugfs_data; #endif /* * Encapsulate all poll related data of a single xbus. */ struct xbus_poller { /* * Bus scanning */ xbus_t *xbus; struct workqueue_struct *wq; bool is_polling; atomic_t count_poll_answers; struct list_head poll_results; wait_queue_head_t wait_for_polls; struct work_struct xpds_init_work; atomic_t count_xpds_to_initialize; atomic_t count_xpds_initialized; wait_queue_head_t wait_for_xpd_initialization; }; /* * An xbus is a transport layer for Xorcom Protocol commands */ struct xbus { char busname[XBUS_NAMELEN]; /* only xbus_new set this */ char busdesc[XBUS_DESCLEN]; /* lowlevel drivers set this */ int num; xbus_ops_t *ops; struct xpd *xpds[MAX_XPDS]; int max_packet_size; /* Device-Model */ struct device astribank; #define dev_to_xbus(dev) container_of(dev, struct xbus, astribank) /* Simulator data */ xbus_type_t bus_type; spinlock_t lock; atomic_t pcm_nesting; bool hardware_exists; /* Hardware is functional */ int open_counter; /* Number of open channels */ atomic_t packet_counter; /* Allocated packets */ wait_queue_head_t packet_cache_empty; /* PCM metrics */ struct timeval last_tx_sync; struct timeval last_rx_sync; unsigned long max_tx_sync; unsigned long min_tx_sync; unsigned long max_rx_sync; unsigned long min_rx_sync; struct xbus_poller *poller; /* * Sync adjustment */ int sync_adjustment; int sync_adjustment_offset; long pll_updated_at; struct rw_semaphore in_use; int num_xpds; void *priv; /* Pointer to transport level data structures */ #ifdef XPP_DEBUGFS struct dentry *debugfs_dir; struct dentry *debugfs_file; struct debugfs_data *debugfs_data; #endif #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_xbus_dir; struct proc_dir_entry *proc_xbus_summary; struct proc_dir_entry *proc_xbus_waitfor_xpds; #ifdef PROTOCOL_DEBUG struct proc_dir_entry *proc_xbus_command; #endif #endif /* statistics */ int counters[XBUS_COUNTER_MAX]; }; #endif typedef enum xpd_direction { TO_PSTN = 0, TO_PHONE = 1, } xpd_direction_t; #ifdef __KERNEL__ /* * XPD statistics counters */ enum { XPD_N_PCM_READ, XPD_N_PCM_WRITE, XPD_N_RECV_ERRORS, }; #define XPD_COUNTER(xpd, counter) ((xpd)->counters[XPD_N_ ## counter]) #define C_(x) [ XPD_N_ ## x ] = { #x } /* yucky, make an instance so we can size it... */ static struct xpd_counters { char *name; } xpd_counters[] = { C_(PCM_READ), C_(PCM_WRITE), C_(RECV_ERRORS), }; #undef C_ #define XPD_COUNTER_MAX (sizeof(xpd_counters)/sizeof(xpd_counters[0])) /* * An XPD is a single Xorcom Protocol Device */ struct xpd { char xpdname[XPD_NAMELEN]; struct zt_span span; struct zt_chan *chans; int channels; xpd_type_t type; const char *type_name; byte subtype; byte revision; /* Card revision */ xpd_direction_t direction; /* TO_PHONE, TO_PSTN */ xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */ xpp_line_t offhook; /* Actual chip state: 0 - ONHOOK, 1 - OFHOOK */ xpp_line_t cid_on; xpp_line_t msg_waiting; /* Voice Mail Waiting Indication */ xpp_line_t digital_outputs; /* 0 - no, 1 - yes */ xpp_line_t digital_inputs; /* 0 - no, 1 - yes */ xpp_line_t digital_signalling; /* PRI/BRI signalling channels */ /* maintained by card drivers */ uint pcm_len; /* allocation length of PCM packet (dynamic) */ xpp_line_t wanted_pcm_mask; bool ringing[CHANNELS_PERXPD]; xbus_t *xbus; /* The XBUS we are connected to */ spinlock_t lock; atomic_t zt_registered; /* Am I fully registered with zaptel */ atomic_t open_counter; /* Number of open channels */ int flags; bool blink_mode; /* for visual identification */ #define DEFAULT_LED_PERIOD (1000/8) /* in tick */ #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_xpd_dir; struct proc_dir_entry *proc_xpd_summary; struct proc_dir_entry *proc_xpd_ztregister; struct proc_dir_entry *proc_xpd_blink; #endif int counters[XPD_COUNTER_MAX]; const xproto_table_t *xproto; /* Card level protocol table */ const xops_t *xops; /* Card level operations */ void *priv; /* Card level private data */ bool card_present; reg_cmd_t requested_reply; reg_cmd_t last_reply; unsigned long last_response; /* in jiffies */ unsigned xbus_idx; /* index in xbus->xpds[] */ xpd_addr_t addr; struct list_head xpd_list; unsigned int timer_count; volatile u_char *readchunk; /* Double-word aligned read memory */ /* Echo cancelation */ u_char ec_chunk1[CHANNELS_PERXPD][ZT_CHUNKSIZE]; u_char ec_chunk2[CHANNELS_PERXPD][ZT_CHUNKSIZE]; }; #define for_each_line(xpd,i) for((i) = 0; (i) < (xpd)->channels; (i)++) #define IS_BRI(xpd) ((xpd)->type == XPD_TYPE_BRI_NT || (xpd)->type == XPD_TYPE_BRI_TE) #define TICK_TOLERANCE 500 /* usec */ #ifdef DEBUG_SYNC_PARPORT void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1); #else #define xbus_flip_bit(xbus, bitnum0, bitnum1) #endif #endif #endif /* XPD_H */