#ifndef XPD_H #define XPD_H /* * Written by Oron Peled * Copyright (C) 2004-2005, 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 #endif #include #ifdef __KERNEL__ #define DEF_PARM(type,name,init,desc) \ type name = init; \ module_param(name, type, 0600); \ MODULE_PARM_DESC(name, desc) #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__ #define MAX_SPANNAME 20 #define MAX_SPANDESC 40 #define MAX_CHANNAME 20 #define XPD_NAMELEN 10 /* must be <= from maximal workqueue name */ #define XPD_DESCLEN 20 #define XBUS_NAMELEN 20 /* must be <= from maximal workqueue name */ #define XBUS_DESCLEN 40 /* Hardware does not check bank_num yet. So only 4 cards can be used */ #define MAX_XPDS 4 // 1 FXS + 2 E1/T1 + 1 (Quad * E1/T1) #define VALID_XPD_NUM(x) ((x) < MAX_XPDS && (x) >= 0) 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 (*packet_send)(xbus_t *xbus, xpacket_t *packet); xpacket_t *(*packet_new)(xbus_t *xbus, int flags); void (*packet_free)(xbus_t *xbus, xpacket_t *p); }; enum { XBUS_N_DESC_REQ, XBUS_N_DEV_DESC, XBUS_N_PCM_WRITE, XBUS_N_PCM_READ, XBUS_N_TX_BYTES, XBUS_N_RX_BYTES, XBUS_N_SOFTSIM_PACKETS, XBUS_N_SIM_PACKETS, }; #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), C_(PCM_WRITE), C_(PCM_READ), C_(TX_BYTES), C_(RX_BYTES), C_(SOFTSIM_PACKETS), C_(SIM_PACKETS), }; #undef C_ #define XBUS_COUNTER_MAX ARRAY_SIZE(xbus_counters) struct xpd_sim { bool simulated; bool softloop_xpd; int loopto; xpd_type_t xpd_type; xpp_line_t hookstate; }; 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]; /* Simulator data */ xbus_type_t bus_type; #if SOFT_SIMULATOR struct xpd_sim sim[MAX_XPDS]; struct workqueue_struct *sim_workqueue; struct work_struct sim_work; // workqueue job for running simulator packet_queue_t sim_packet_queue; #endif spinlock_t lock; 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; struct timer_list poll_timer; struct rw_semaphore in_use; int num_xpds; void *priv; /* Pointer to transport level data structures */ #ifdef XPP_PACKET_LOG struct cyclic_buff *packet_log; #endif #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_xbus_dir; struct proc_dir_entry *proc_xbus_summary; #endif /* statistics */ int counters[XBUS_COUNTER_MAX]; }; #endif typedef enum xpd_direction { TO_PHONE = 0, TO_PSTN = 1, } xpd_direction_t; #define LINE_BITS (sizeof(xpp_line_t)*8) #ifdef __KERNEL__ #define BIT_SET(x,i) ((x) |= (1 << (i))) #define BIT_CLR(x,i) ((x) &= ~(1 << (i))) #define IS_SET(x,i) (((x) & (1 << (i))) != 0) #define BIT(i) (1 << (i)) 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])) enum leds { LED_GREEN, LED_RED, LED_BLUE, }; #define NUM_LEDS 3 struct xpd { char xpdname[XPD_NAMELEN]; struct zt_span span; struct zt_chan *chans; int channels; xpd_type_t type; xpd_direction_t direction; /* TO_PHONE, TO_PSTN */ xpp_line_t enabled_chans; /* hardware activation: 0 - off, 1 - on */ xpp_line_t hookstate; /* 0 - ONHOOK, 1 - OFHOOK */ xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */ xpp_line_t digital_outputs; /* 0 - no, 1 - yes */ xpp_line_t digital_inputs; /* 0 - no, 1 - yes */ int ringing[CHANNELS_PERXPD]; bool ringer_on[CHANNELS_PERXPD]; /* For ring toggling */ bool led_on[CHANNELS_PERXPD]; /* For led toggling */ int lasttxhook[CHANNELS_PERXPD]; struct work_struct xpd_post_init; xbus_t *xbus; spinlock_t lock; atomic_t open_counter; /* Number of open channels */ int flags; unsigned int board_flags; #define XPD_BOARD_LOOPBACK 1 #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; #endif // Bit numbers of board_flags int counters[XPD_COUNTER_MAX]; const xops_t *xops; /* Card level operations */ void *priv; /* Card level private data */ atomic_t card_present; unsigned int recv_errors; unsigned int seq_errors; unsigned long last_response; /* in jiffies */ unsigned id; struct list_head xpd_list; unsigned int timer_count; volatile u_char *writechunk; /* Double-word aligned write memory */ 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]; }; #endif #endif /* XPD_H */