58c1168185
voicebus_quiesce is like voicebus_stop, except that it doesn't wait for any information to come back from the card. This prevents kexec from blocking waiting for information from a potentially dead card. Signed-off-by: Shaun Ruffell <sruffell@digium.com> Acked-by: Michael Spiceland <mspiceland@digium.com> Acked-by: Kinsey Moore <kmoore@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9880 a0bf4364-ded3-4de4-8d8a-66a801d63aff
247 lines
6.4 KiB
C
247 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>
|
|
|
|
|
|
#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
|
|
|
|
#ifdef VOICEBUS_NET_DEBUG
|
|
#include <linux/skbuff.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/etherdevice.h>
|
|
#endif
|
|
|
|
struct voicebus;
|
|
|
|
struct vbb {
|
|
u8 data[VOICEBUS_SFRAME_SIZE];
|
|
struct list_head entry;
|
|
dma_addr_t dma_addr;
|
|
};
|
|
|
|
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;
|
|
struct dma_pool *pool;
|
|
|
|
#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
|
|
};
|
|
|
|
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);
|
|
void voicebus_quiesce(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__ */
|