464 lines
10 KiB
C
464 lines
10 KiB
C
/*****************************************************************************
|
|
* if_wanpipe_common.h Sangoma Driver/Socket common area definitions.
|
|
*
|
|
* Author: Nenad Corbic <ncorbic@sangoma.com>
|
|
*
|
|
* Copyright: (c) 2000 Sangoma Technologies Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
* ============================================================================
|
|
* Jan 13, 2000 Nenad Corbic Initial version
|
|
*****************************************************************************/
|
|
|
|
|
|
#ifndef _WANPIPE_SOCK_DRIVER_COMMON_H
|
|
#define _WANPIPE_SOCK_DRIVER_COMMON_H
|
|
|
|
#if defined(WAN_KERNEL)
|
|
|
|
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
|
# include <wanpipe_debug.h>
|
|
# include <wanpipe_common.h>
|
|
# include <wanpipe_kernel.h>
|
|
#elif defined(__LINUX__)
|
|
# include <linux/version.h>
|
|
# include <linux/wanpipe_debug.h>
|
|
# include <linux/wanpipe_common.h>
|
|
# include <linux/wanpipe_kernel.h>
|
|
# include <linux/if_wanpipe.h>
|
|
#elif defined(__WINDOWS__)
|
|
# include <wanpipe_debug.h>
|
|
# include <wanpipe_common.h>
|
|
# include <wanpipe_kernel.h>
|
|
#endif
|
|
|
|
|
|
/*#define wan_next_dev(dev) *((netdevice_t**)dev->priv)*/
|
|
#define wan_next_dev(dev) *((netdevice_t**)wan_netif_priv(dev))
|
|
|
|
typedef struct {
|
|
int (*open) (netdevice_t*);
|
|
int (*close) (netdevice_t*);
|
|
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
|
int (*output) (netdevice_t*,netskb_t*,struct sockaddr*, struct rtentry*);
|
|
#else
|
|
int (*send) (netskb_t* skb, netdevice_t*);
|
|
struct net_device_stats* (*get_stats) (netdevice_t*);
|
|
#endif
|
|
int (*ioctl) (netdevice_t*, struct ifreq*, wan_ioctl_cmd_t);
|
|
void (*tx_timeout) (netdevice_t*);
|
|
} wanpipe_common_iface_t;
|
|
|
|
typedef struct {
|
|
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
|
/* !!! IMPORTANT !!! <- Do not move this parameter (GENERIC-PPP) */
|
|
void *prot_ptr;
|
|
/* netdevice_t *next; */ /* netdevice_t *slave; */
|
|
void *card;
|
|
netdevice_t *dev;
|
|
struct mtx ifmtx;
|
|
unsigned char state;
|
|
unsigned char usedby;
|
|
wan_tasklet_t bh_task;
|
|
wan_timer_t dev_timer;
|
|
struct socket *sk; /* Wanpipe Sock bind's here (Not used)*/
|
|
unsigned int protocol;
|
|
unsigned short lcn;
|
|
void *lip;
|
|
unsigned int lip_prot;
|
|
int is_spppdev; /* special mode for ADSL PPP_VC/PPP_LLC */
|
|
# if defined(NETGRAPH)
|
|
char ng_nodename [NG_NODELEN+1];
|
|
int ng_running;
|
|
node_p ng_node;
|
|
hook_p ng_upper_hook;
|
|
hook_p ng_lower_hook;
|
|
hook_p ng_debug_hook;
|
|
int ng_lowerhooks;
|
|
int ng_upperhooks;
|
|
int ng_datahooks;
|
|
struct ifqueue lo_queue;
|
|
struct ifqueue hi_queue;
|
|
short ng_timeout;
|
|
struct callout ng_timeout_handle;
|
|
u_long ng_out_deficit; /* output since last input */
|
|
u_char ng_promisc; /* promiscuous mode enabled */
|
|
u_char ng_autoSrcAddr; /* always overwrite source address */
|
|
# endif
|
|
#elif defined(__LINUX__)
|
|
/* !!! IMPORTANT !!! <- Do not move this parameter (GENERIC-PPP) */
|
|
void* *prot_ptr;
|
|
netdevice_t *next; /*slave;*/
|
|
void *card;
|
|
struct net_device_stats if_stats;
|
|
|
|
atomic_t receive_block;
|
|
atomic_t command;
|
|
atomic_t disconnect;
|
|
|
|
struct sock *sk; /* Wanpipe Sock bind's here */
|
|
|
|
struct tq_struct wanpipe_task; /* Immediate BH handler task */
|
|
|
|
unsigned char rw_bind; /* Sock bind state */
|
|
unsigned char usedby;
|
|
unsigned char state;
|
|
unsigned char svc;
|
|
unsigned short lcn;
|
|
unsigned int config_id;
|
|
|
|
unsigned long used;
|
|
unsigned long api_state;
|
|
netdevice_t *dev;
|
|
wan_skb_queue_t rx_queue;
|
|
wan_tasklet_t bh_task;
|
|
wan_timer_t dev_timer;
|
|
|
|
unsigned int protocol;
|
|
|
|
void *lip;
|
|
unsigned int lip_prot;
|
|
#elif defined(__WINDOWS__)
|
|
|
|
void *prot_ptr;
|
|
netdevice_t* dev;
|
|
unsigned char state;
|
|
unsigned char usedby;
|
|
|
|
void *card;
|
|
|
|
void* sk;
|
|
|
|
void *lip;
|
|
|
|
//A104 additions
|
|
unsigned int protocol;
|
|
wan_tasklet_t bh_task;
|
|
|
|
//ADSL additions
|
|
wan_tasklet_t wanpipe_task; /* Immediate BH handler task */
|
|
unsigned int lip_prot;
|
|
#endif
|
|
int is_netdev;
|
|
wanpipe_common_iface_t iface;
|
|
} wanpipe_common_t;
|
|
|
|
/* Used flags: Resources */
|
|
enum {
|
|
LCN_USED,
|
|
LCN_DEV,
|
|
LCN_TX_DEV,
|
|
LCN_X25_LINK,
|
|
LCN_SK_ID,
|
|
LCN_DSP_ID,
|
|
WAN_API_INIT
|
|
};
|
|
|
|
#define SK_ID LCN_SK_ID
|
|
|
|
|
|
enum {
|
|
WANSOCK_UNCONFIGURED, /* link/channel is not configured */
|
|
WANSOCK_DISCONNECTED, /* link/channel is disconnected */
|
|
WANSOCK_CONNECTING, /* connection is in progress */
|
|
WANSOCK_CONNECTED, /* link/channel is operational */
|
|
WANSOCK_LIMIT, /* for verification only */
|
|
WANSOCK_DUALPORT, /* for Dual Port cards */
|
|
WANSOCK_DISCONNECTING,
|
|
WANSOCK_BINDED,
|
|
WANSOCK_BIND_LISTEN,
|
|
WANSOCK_LISTEN
|
|
};
|
|
|
|
|
|
static __inline void *wan_get_lip_ptr(netdevice_t *dev)
|
|
{
|
|
if (wan_netif_priv(dev)){
|
|
return ((wanpipe_common_t*)wan_netif_priv(dev))->lip;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static __inline int wan_set_lip_ptr(netdevice_t *dev, void *lipreg)
|
|
{
|
|
if (wan_netif_priv(dev)){
|
|
((wanpipe_common_t*)wan_netif_priv(dev))->lip = lipreg;
|
|
return 0;
|
|
}
|
|
return -ENODEV;
|
|
}
|
|
|
|
static __inline int wan_set_lip_prot(netdevice_t *dev, int protocol)
|
|
{
|
|
if (wan_netif_priv(dev)){
|
|
((wanpipe_common_t*)wan_netif_priv(dev))->lip_prot = protocol;
|
|
return 0;
|
|
}
|
|
return -ENODEV;
|
|
}
|
|
|
|
|
|
static __inline int wan_api_rx(void *chan_ptr,netskb_t *skb)
|
|
{
|
|
#if defined(__LINUX__)
|
|
wanpipe_common_t *chan = (wanpipe_common_t*)chan_ptr;
|
|
|
|
if (test_bit(SK_ID,&chan->used) && chan->sk){
|
|
return wanpipe_api_sock_rx(skb,chan->dev,chan->sk);
|
|
}
|
|
#endif
|
|
return -EINVAL;
|
|
}
|
|
|
|
static __inline int wan_api_rx_dtmf(void *chan_ptr,netskb_t *skb)
|
|
{
|
|
#if defined(__LINUX__)
|
|
wanpipe_common_t *chan = (wanpipe_common_t*)chan_ptr;
|
|
|
|
if (test_bit(SK_ID,&chan->used) && chan->sk){
|
|
return wanpipe_api_sock_rx(skb,chan->dev,chan->sk);
|
|
}
|
|
#endif
|
|
return -EINVAL;
|
|
}
|
|
|
|
static __inline void wan_wakeup_api(void *chan_ptr)
|
|
{
|
|
#if defined(__LINUX__)
|
|
wanpipe_common_t *chan = (wanpipe_common_t*)chan_ptr;
|
|
|
|
if (test_bit(SK_ID,&chan->used) && chan->sk){
|
|
wanpipe_api_poll_wake(chan->sk);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
static __inline int wan_reg_api(void *chan_ptr, void *dev, char *devname)
|
|
{
|
|
#if defined(__LINUX__)
|
|
wanpipe_common_t *common = (wanpipe_common_t*)chan_ptr;
|
|
|
|
if (wan_test_and_set_bit(WAN_API_INIT,&common->used)){
|
|
DEBUG_EVENT("%s: Error: Failed to initialize API!\n",
|
|
devname);
|
|
return -EINVAL;
|
|
}
|
|
|
|
DEBUG_TEST("%s: Initializing API\n",
|
|
devname);
|
|
|
|
common->sk=NULL;
|
|
common->state = WAN_CONNECTING;
|
|
common->dev = dev;
|
|
common->api_state=0;
|
|
|
|
WAN_IFQ_INIT(&common->rx_queue,10);
|
|
|
|
/*WAN_TASKLET_INIT((&common->task),0,func,(unsigned long)common);*/
|
|
|
|
wan_set_bit(WAN_API_INIT,&common->used);
|
|
#else
|
|
DEBUG_EVENT("%s: Initializing API\n",
|
|
devname);
|
|
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static __inline int wan_unreg_api(void *chan_ptr, char *devname)
|
|
{
|
|
#if defined(__LINUX__)
|
|
wanpipe_common_t *common = (wanpipe_common_t*)chan_ptr;
|
|
|
|
if (!wan_test_and_clear_bit(WAN_API_INIT,&common->used)){
|
|
DEBUG_EVENT("%s: Error: Failed to unregister API!\n",
|
|
devname);
|
|
return -EINVAL;
|
|
}
|
|
|
|
DEBUG_EVENT("%s: Unregistering API\n",
|
|
devname);
|
|
|
|
common->state = WAN_DISCONNECTED;
|
|
// WAN_TASKLET_KILL((&common->task));
|
|
wan_skb_queue_purge(&common->rx_queue);
|
|
#else
|
|
DEBUG_EVENT("%s: Unregistering API\n",
|
|
devname);
|
|
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static __inline void wan_release_svc_dev(wanpipe_common_t *chan)
|
|
{
|
|
#if defined(__LINUX__)
|
|
wan_clear_bit(0,(void *)&chan->rw_bind);
|
|
#endif
|
|
}
|
|
|
|
static __inline void wan_get_svc_dev(wanpipe_common_t *chan)
|
|
{
|
|
#if defined(__LINUX__)
|
|
wan_set_bit(0,(void *)&chan->rw_bind);
|
|
#endif
|
|
}
|
|
|
|
|
|
static __inline int wan_bind_api_to_svc(void *chan_ptr, void *sk_id)
|
|
{
|
|
#if defined(__LINUX__)
|
|
wanpipe_common_t *chan = (wanpipe_common_t*)chan_ptr;
|
|
|
|
if (!sk_id){
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (test_bit(SK_ID,&chan->used) || chan->sk){
|
|
return -EBUSY;
|
|
}
|
|
|
|
wan_get_svc_dev(chan);
|
|
chan->sk = sk_id;
|
|
sock_hold(chan->sk);
|
|
wan_set_bit(SK_ID,&chan->used);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
static __inline int wan_unbind_api_from_svc(void *chan_ptr, void *sk_id)
|
|
{
|
|
#if defined(__LINUX__)
|
|
wanpipe_common_t *chan=(wanpipe_common_t*)chan_ptr;
|
|
|
|
WAN_ASSERT_EINVAL((!chan));
|
|
WAN_ASSERT_EINVAL((!chan->dev));
|
|
|
|
DEBUG_TEST("%s:%s: BEGIN\n",__FUNCTION__,chan->dev->name);
|
|
|
|
if (test_bit(SK_ID,&chan->used) && chan->sk){
|
|
|
|
if ((struct sock*)sk_id != chan->sk){
|
|
DEBUG_TEST("%s: ERROR: API trying to unbind invalid sock api! New=%p Orig=%p\n",
|
|
chan->dev->name,sk_id,chan->sk);
|
|
return -ENODEV;
|
|
}
|
|
|
|
wan_clear_bit(SK_ID,&chan->used);
|
|
__sock_put(chan->sk);
|
|
chan->sk=NULL;
|
|
|
|
DEBUG_TEST("%s SK UNBIND SUCCESS\n",
|
|
__FUNCTION__);
|
|
|
|
wan_release_svc_dev(chan);
|
|
return 0;
|
|
}
|
|
|
|
DEBUG_TEST("%s: ERROR: API trying to unbind invalid sock api! New=%p Orig=%p\n",
|
|
chan->dev->name,sk_id,chan->sk);
|
|
return -ENODEV;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
|
|
static __inline void wan_update_api_state(void *chan_ptr)
|
|
{
|
|
|
|
#if defined(__LINUX__)
|
|
|
|
int err=0;
|
|
wanpipe_common_t *chan = (wanpipe_common_t*)chan_ptr;
|
|
|
|
/* If the LCN state changes from Connected to Disconnected, and
|
|
* we are in the API mode, then notify the socket that the
|
|
* connection has been lost */
|
|
|
|
if (chan->usedby != API)
|
|
return;
|
|
|
|
if (test_bit(SK_ID,&chan->used) && chan->sk){
|
|
|
|
if (chan->state != WAN_CONNECTED && test_bit(0,&chan->api_state)){
|
|
wan_clear_bit(0,&chan->api_state);
|
|
protocol_disconnected (chan->sk);
|
|
return;
|
|
}
|
|
|
|
|
|
if (chan->state == WAN_CONNECTED){
|
|
wan_set_bit(0,&chan->api_state);
|
|
err=protocol_connected (chan->dev,chan->sk);
|
|
if (err == -EINVAL){
|
|
printk(KERN_INFO "%s:Major Error in Socket Above: CONN!!!\n",
|
|
chan->dev->name);
|
|
wan_unbind_api_from_svc(chan,chan->sk);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (chan->state == WAN_DISCONNECTED){
|
|
err = protocol_disconnected (chan->sk);
|
|
}
|
|
}else{
|
|
DEBUG_TEST("%s: Error: no sk device\n",__FUNCTION__);
|
|
}
|
|
|
|
if (chan->state != WAN_CONNECTED){
|
|
wan_clear_bit(0,&chan->api_state);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
#define MAX_API_RX_QUEUE 10
|
|
static __inline int wan_api_enqueue_skb(void *chan_ptr,netskb_t *skb)
|
|
{
|
|
#if defined(__LINUX__)
|
|
wanpipe_common_t *chan = (wanpipe_common_t*)chan_ptr;
|
|
|
|
if (wan_skb_queue_len(&chan->rx_queue) > MAX_API_RX_QUEUE){
|
|
return -EBUSY;
|
|
}
|
|
wan_skb_queue_tail(&chan->rx_queue,skb);
|
|
|
|
if (wan_skb_queue_len(&chan->rx_queue) >= MAX_API_RX_QUEUE){
|
|
return 1;
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static __inline netskb_t* wan_api_dequeue_skb(void *chan_ptr)
|
|
{
|
|
#if defined(__LINUX__)
|
|
wanpipe_common_t *chan = (wanpipe_common_t*)chan_ptr;
|
|
return wan_skb_dequeue(&chan->rx_queue);
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
|
|
}
|
|
|
|
#if 0
|
|
void wp_debug_func_init(void)
|
|
{
|
|
DBG_ARRAY_CNT=0;
|
|
}
|
|
#endif
|
|
|
|
|
|
#endif /* WAN_KERNEL */
|
|
|
|
|
|
#endif
|