summaryrefslogtreecommitdiff
path: root/drivers/dahdi/voicebus/voicebus.h
blob: de565d9e16d5f3db4aa787c54b453d9d76d8efe9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
 * VoiceBus(tm) Interface Library.
 *
 * Written by Shaun Ruffell <sruffell@digium.com>
 * and based on previous work by Mark Spencer <markster@digium.com>, 
 * Matthew Fredrickson <creslin@digium.com>, and
 * Michael Spiceland <mspiceland@digium.com>
 * 
 * Copyright (C) 2007-2010 Digium, Inc.
 *
 * All rights reserved.
 *
 */

/*
 * See http://www.asterisk.org for more information about
 * the Asterisk project. Please do not directly contact
 * any of the maintainers of this project for assistance;
 * the project provides a web site, mailing lists and IRC
 * channels for your use.
 *
 * This program is free software, distributed under the terms of
 * the GNU General Public License Version 2 as published by the
 * Free Software Foundation. See the LICENSE file included with
 * this program for more details.
 */


#ifndef __VOICEBUS_H__
#define __VOICEBUS_H__

#include <linux/interrupt.h>


#ifdef VOICEBUS_NET_DEBUG
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#endif

#define VOICEBUS_DEFAULT_LATENCY	3U
#define VOICEBUS_DEFAULT_MAXLATENCY	25U
#define VOICEBUS_MAXLATENCY_BUMP	6U

#define VOICEBUS_SFRAME_SIZE 1004U

/*! The number of descriptors in both the tx and rx descriptor ring. */
#define DRING_SIZE	(1 << 7)  /* Must be a power of 2 */
#define DRING_MASK	(DRING_SIZE-1)

/* Define CONFIG_VOICEBUS_SYSFS to create some attributes under the pci device.
 * This is disabled by default because it hasn't been tested on the full range
 * of supported kernels. */
#undef CONFIG_VOICEBUS_SYSFS

/* Do not generate interrupts on this interface, but instead just poll it */
#undef CONFIG_VOICEBUS_TIMER

/* Define this in order to create a debugging network interface. */
#undef VOICEBUS_NET_DEBUG

struct voicebus;

struct vbb {
	u8 data[VOICEBUS_SFRAME_SIZE];
	struct list_head entry;
};

struct voicebus_operations {
	void (*handle_receive)(struct voicebus *vb, struct list_head *buffers);
	void (*handle_transmit)(struct voicebus *vb, struct list_head *buffers);
	void (*handle_error)(struct voicebus *vb);
};

/**
 * struct voicebus_descriptor_list - A single descriptor list.
 */
struct voicebus_descriptor_list {
	struct voicebus_descriptor *desc;
	unsigned int 	head;
	unsigned int 	tail;
	void  		*pending[DRING_SIZE];
	dma_addr_t	desc_dma;
	atomic_t 	count;
	unsigned int	padding;
};

/* Bit definitions for struct voicebus.flags */
#define VOICEBUS_STOP				1
#define VOICEBUS_STOPPED			2
#define VOICEBUS_LATENCY_LOCKED			3
#define VOICEBUS_NORMAL_MODE			4
#define VOICEBUS_USERMODE			5

/**
 * struct voicebus - Represents physical interface to voicebus card.
 *
 * @tx_complete: only used in the tasklet to temporarily hold complete tx
 *		 buffers.
 */
struct voicebus {
	struct pci_dev		*pdev;
	spinlock_t		lock;
	struct voicebus_descriptor_list rxd;
	struct voicebus_descriptor_list txd;
	u8			*idle_vbb;
	dma_addr_t		idle_vbb_dma_addr;
	const int		*debug;
	void __iomem 		*iobase;
	struct tasklet_struct 	tasklet;

#if defined(CONFIG_VOICEBUS_TIMER)
	struct timer_list	timer;
#endif

	struct work_struct	underrun_work;
	const struct voicebus_operations *ops;
	unsigned long		flags;
	unsigned int		min_tx_buffer_count;
	unsigned int		max_latency;
	struct list_head	tx_complete;

#ifdef VOICEBUS_NET_DEBUG
	struct sk_buff_head captured_packets;
	struct net_device *netdev;
	struct net_device_stats net_stats;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
	struct napi_struct napi;
#endif
	atomic_t tx_seqnum;
	atomic_t rx_seqnum;
#endif
};

#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
extern kmem_cache_t *voicebus_vbb_cache;
#else
extern struct kmem_cache *voicebus_vbb_cache;
#endif

int __voicebus_init(struct voicebus *vb, const char *board_name,
		    int normal_mode);
void voicebus_release(struct voicebus *vb);
int voicebus_start(struct voicebus *vb);
int voicebus_stop(struct voicebus *vb);
int voicebus_transmit(struct voicebus *vb, struct vbb *vbb);
int voicebus_set_minlatency(struct voicebus *vb, unsigned int milliseconds);
int voicebus_current_latency(struct voicebus *vb);

static inline int voicebus_init(struct voicebus *vb, const char *board_name)
{
	return __voicebus_init(vb, board_name, 1);
}

static inline int
voicebus_no_idle_init(struct voicebus *vb, const char *board_name)
{
	return __voicebus_init(vb, board_name, 0);
}

/**
 * voicebus_lock_latency() - Do not increase the latency during underruns.
 *
 */
static inline void voicebus_lock_latency(struct voicebus *vb)
{
	set_bit(VOICEBUS_LATENCY_LOCKED, &vb->flags);
}

/**
 * voicebus_unlock_latency() - Bump up the latency during underruns.
 *
 */
static inline void voicebus_unlock_latency(struct voicebus *vb)
{
	clear_bit(VOICEBUS_LATENCY_LOCKED, &vb->flags);
}

/**
 * voicebus_is_latency_locked() - Return 1 if latency is currently locked.
 *
 */
static inline int voicebus_is_latency_locked(const struct voicebus *vb)
{
	return test_bit(VOICEBUS_LATENCY_LOCKED, &vb->flags);
}

static inline void voicebus_set_normal_mode(struct voicebus *vb)
{
	set_bit(VOICEBUS_NORMAL_MODE, &vb->flags);
}

/**
 * voicebus_set_max_latency() - Set the maximum number of milliseconds the latency will be able to grow to.
 */
static inline void
voicebus_set_maxlatency(struct voicebus *vb, unsigned int max_latency)
{
	spin_lock_bh(&vb->lock);
	vb->max_latency = clamp(max_latency,
				vb->min_tx_buffer_count,
				VOICEBUS_DEFAULT_MAXLATENCY);
	spin_unlock_bh(&vb->lock);
}
#endif /* __VOICEBUS_H__ */