dahdi-linux/drivers/dahdi/voicebus/voicebus.h
2010-09-11 19:25:52 +00:00

250 lines
6.4 KiB
C

/*
* 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
/* Define this to only run the processing in an interrupt handler
* (and not tasklet). */
#define CONFIG_VOICEBUS_INTERRUPT
/* Define this to use a FIFO for the software echocan reference.
* (experimental) */
#undef CONFIG_VOICEBUS_ECREFERENCE
#ifdef CONFIG_VOICEBUS_ECREFERENCE
struct dahdi_fifo;
unsigned int __dahdi_fifo_put(struct dahdi_fifo *fifo, u8 *data, size_t size);
unsigned int __dahdi_fifo_get(struct dahdi_fifo *fifo, u8 *data, size_t size);
void dahdi_fifo_free(struct dahdi_fifo *fifo);
struct dahdi_fifo *dahdi_fifo_alloc(size_t maxsize, gfp_t alloc_flags);
#endif
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_SHUTDOWN 0
#define VOICEBUS_STOP 1
#define VOICEBUS_STOPPED 2
#define VOICEBUS_LATENCY_LOCKED 3
#define VOICEBUS_HARD_UNDERRUN 4
/**
* voicebus_mode
*
* NORMAL: For non-hx8 boards. Uses idle_buffers.
* BOOT: For hx8 boards. For sending single packets at a time.
* HX8: Normal operating mode for Hx8 Boards. Does not use
* idle_buffers.
*/
enum voicebus_mode {
NORMAL = 0,
BOOT = 1,
HX8 = 2,
};
/**
* 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;
enum voicebus_mode mode;
#if defined(CONFIG_VOICEBUS_INTERRUPT)
atomic_t deferred_disabled_count;
#endif
#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;
struct list_head free_rx;
#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,
enum voicebus_mode mode);
void voicebus_release(struct voicebus *vb);
int voicebus_start(struct voicebus *vb);
void 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, NORMAL);
}
static inline int
voicebus_boot_init(struct voicebus *vb, const char *board_name)
{
return __voicebus_init(vb, board_name, BOOT);
}
/**
* 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)
{
vb->mode = NORMAL;
}
static inline void voicebus_set_hx8_mode(struct voicebus *vb)
{
vb->mode = HX8;
}
/**
* 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)
{
unsigned long flags;
spin_lock_irqsave(&vb->lock, flags);
vb->max_latency = clamp(max_latency,
vb->min_tx_buffer_count,
VOICEBUS_DEFAULT_MAXLATENCY);
spin_unlock_irqrestore(&vb->lock, flags);
}
#endif /* __VOICEBUS_H__ */