dahdi: Register devices instead of individual spans.
Increasingly, spans are implemented by devices that support more than a single span. Introduce a 'struct dahdi_device' object which explicitly contains multiple spans. This will allow a cleaner representation of spans and devices in sysfs since order of arrival will not determine the layout of the devices. This also gives the core of dahdi a way to know the relationship between spans. This generalizes similar concepts that were previously xpp specific. The conversion of the xpp code was almost entirely done by Oron and Tzafrir. Signed-off-by: Shaun Ruffell <sruffell@digium.com> Signed-off-by: Oron Peled <oron.peled@xorcom.com> Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10273 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
parent
38c3cda8e2
commit
935c9ba50a
@ -108,8 +108,6 @@
|
|||||||
EXPORT_SYMBOL(dahdi_transcode_fops);
|
EXPORT_SYMBOL(dahdi_transcode_fops);
|
||||||
EXPORT_SYMBOL(dahdi_init_tone_state);
|
EXPORT_SYMBOL(dahdi_init_tone_state);
|
||||||
EXPORT_SYMBOL(dahdi_mf_tone);
|
EXPORT_SYMBOL(dahdi_mf_tone);
|
||||||
EXPORT_SYMBOL(dahdi_register);
|
|
||||||
EXPORT_SYMBOL(dahdi_unregister);
|
|
||||||
EXPORT_SYMBOL(__dahdi_mulaw);
|
EXPORT_SYMBOL(__dahdi_mulaw);
|
||||||
EXPORT_SYMBOL(__dahdi_alaw);
|
EXPORT_SYMBOL(__dahdi_alaw);
|
||||||
#ifdef CONFIG_CALC_XLAW
|
#ifdef CONFIG_CALC_XLAW
|
||||||
@ -399,7 +397,7 @@ __for_each_channel(unsigned long (*func)(struct dahdi_chan *chan,
|
|||||||
struct dahdi_span *s;
|
struct dahdi_span *s;
|
||||||
struct pseudo_chan *pseudo;
|
struct pseudo_chan *pseudo;
|
||||||
|
|
||||||
list_for_each_entry(s, &span_list, node) {
|
list_for_each_entry(s, &span_list, spans_node) {
|
||||||
unsigned long x;
|
unsigned long x;
|
||||||
for (x = 0; x < s->channels; x++) {
|
for (x = 0; x < s->channels; x++) {
|
||||||
struct dahdi_chan *const chan = s->chans[x];
|
struct dahdi_chan *const chan = s->chans[x];
|
||||||
@ -439,7 +437,7 @@ static struct dahdi_chan *_chan_from_num(unsigned int channo)
|
|||||||
/* When searching for the channel amongst the spans, we can use the
|
/* When searching for the channel amongst the spans, we can use the
|
||||||
* fact that channels on a span must be numbered consecutively to skip
|
* fact that channels on a span must be numbered consecutively to skip
|
||||||
* checking each individual channel. */
|
* checking each individual channel. */
|
||||||
list_for_each_entry(s, &span_list, node) {
|
list_for_each_entry(s, &span_list, spans_node) {
|
||||||
unsigned int basechan;
|
unsigned int basechan;
|
||||||
struct dahdi_chan *chan;
|
struct dahdi_chan *chan;
|
||||||
|
|
||||||
@ -488,7 +486,7 @@ static inline struct dahdi_chan *chan_from_file(struct file *file)
|
|||||||
static struct dahdi_span *_find_span(int spanno)
|
static struct dahdi_span *_find_span(int spanno)
|
||||||
{
|
{
|
||||||
struct dahdi_span *s;
|
struct dahdi_span *s;
|
||||||
list_for_each_entry(s, &span_list, node) {
|
list_for_each_entry(s, &span_list, spans_node) {
|
||||||
if (s->spanno == spanno) {
|
if (s->spanno == spanno) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -526,7 +524,7 @@ static unsigned int span_count(void)
|
|||||||
struct dahdi_span *s;
|
struct dahdi_span *s;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
spin_lock_irqsave(&chan_lock, flags);
|
spin_lock_irqsave(&chan_lock, flags);
|
||||||
list_for_each_entry(s, &span_list, node)
|
list_for_each_entry(s, &span_list, spans_node)
|
||||||
++count;
|
++count;
|
||||||
spin_unlock_irqrestore(&chan_lock, flags);
|
spin_unlock_irqrestore(&chan_lock, flags);
|
||||||
return count;
|
return count;
|
||||||
@ -3043,6 +3041,16 @@ static int can_open_timer(void)
|
|||||||
static unsigned int max_pseudo_channels = 512;
|
static unsigned int max_pseudo_channels = 512;
|
||||||
static unsigned int num_pseudo_channels;
|
static unsigned int num_pseudo_channels;
|
||||||
|
|
||||||
|
static int pinned_spans = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dahdi_alloc_pseudo() - Returns a new pseudo channel.
|
||||||
|
*
|
||||||
|
* Call with the registration_mutex held since this function will determine a
|
||||||
|
* channel number, and must be protected from additional registrations while
|
||||||
|
* that is happening.
|
||||||
|
*
|
||||||
|
*/
|
||||||
static struct dahdi_chan *dahdi_alloc_pseudo(struct file *file)
|
static struct dahdi_chan *dahdi_alloc_pseudo(struct file *file)
|
||||||
{
|
{
|
||||||
struct pseudo_chan *pseudo;
|
struct pseudo_chan *pseudo;
|
||||||
@ -3068,8 +3076,6 @@ static struct dahdi_chan *dahdi_alloc_pseudo(struct file *file)
|
|||||||
pseudo->chan.flags = DAHDI_FLAG_AUDIO;
|
pseudo->chan.flags = DAHDI_FLAG_AUDIO;
|
||||||
pseudo->chan.span = NULL; /* No span == psuedo channel */
|
pseudo->chan.span = NULL; /* No span == psuedo channel */
|
||||||
|
|
||||||
mutex_lock(®istration_mutex);
|
|
||||||
|
|
||||||
channo = FIRST_PSEUDO_CHANNEL;
|
channo = FIRST_PSEUDO_CHANNEL;
|
||||||
list_for_each_entry(p, &pseudo_chans, node) {
|
list_for_each_entry(p, &pseudo_chans, node) {
|
||||||
if (channo != p->chan.channo)
|
if (channo != p->chan.channo)
|
||||||
@ -3094,8 +3100,6 @@ static struct dahdi_chan *dahdi_alloc_pseudo(struct file *file)
|
|||||||
list_add(&pseudo->node, pos);
|
list_add(&pseudo->node, pos);
|
||||||
spin_unlock_irqrestore(&chan_lock, flags);
|
spin_unlock_irqrestore(&chan_lock, flags);
|
||||||
|
|
||||||
mutex_unlock(®istration_mutex);
|
|
||||||
|
|
||||||
return &pseudo->chan;
|
return &pseudo->chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3159,7 +3163,9 @@ static int dahdi_open(struct inode *inode, struct file *file)
|
|||||||
if (unit == DAHDI_CHANNEL)
|
if (unit == DAHDI_CHANNEL)
|
||||||
return dahdi_chan_open(file);
|
return dahdi_chan_open(file);
|
||||||
if (unit == DAHDI_PSEUDO) {
|
if (unit == DAHDI_PSEUDO) {
|
||||||
|
mutex_lock(®istration_mutex);
|
||||||
chan = dahdi_alloc_pseudo(file);
|
chan = dahdi_alloc_pseudo(file);
|
||||||
|
mutex_unlock(®istration_mutex);
|
||||||
if (unlikely(!chan))
|
if (unlikely(!chan))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
return dahdi_specchan_open(file);
|
return dahdi_specchan_open(file);
|
||||||
@ -3719,7 +3725,7 @@ static void __dahdi_find_master_span(void)
|
|||||||
|
|
||||||
spin_lock_irqsave(&chan_lock, flags);
|
spin_lock_irqsave(&chan_lock, flags);
|
||||||
old_master = master;
|
old_master = master;
|
||||||
list_for_each_entry(s, &span_list, node) {
|
list_for_each_entry(s, &span_list, spans_node) {
|
||||||
if (s->alarms)
|
if (s->alarms)
|
||||||
continue;
|
continue;
|
||||||
if (dahdi_is_digital_span(s) &&
|
if (dahdi_is_digital_span(s) &&
|
||||||
@ -4241,16 +4247,18 @@ static int dahdi_ioctl_spanstat(struct file *file, unsigned long data)
|
|||||||
spaninfo.linecompat = s->linecompat;
|
spaninfo.linecompat = s->linecompat;
|
||||||
strlcpy(spaninfo.lboname, dahdi_lboname(s->lbo),
|
strlcpy(spaninfo.lboname, dahdi_lboname(s->lbo),
|
||||||
sizeof(spaninfo.lboname));
|
sizeof(spaninfo.lboname));
|
||||||
if (s->manufacturer) {
|
if (s->parent->manufacturer) {
|
||||||
strlcpy(spaninfo.manufacturer, s->manufacturer,
|
strlcpy(spaninfo.manufacturer, s->parent->manufacturer,
|
||||||
sizeof(spaninfo.manufacturer));
|
sizeof(spaninfo.manufacturer));
|
||||||
}
|
}
|
||||||
if (s->devicetype) {
|
if (s->parent->devicetype) {
|
||||||
strlcpy(spaninfo.devicetype, s->devicetype,
|
strlcpy(spaninfo.devicetype, s->parent->devicetype,
|
||||||
sizeof(spaninfo.devicetype));
|
sizeof(spaninfo.devicetype));
|
||||||
}
|
}
|
||||||
strlcpy(spaninfo.location, s->location,
|
if (s->parent->location) {
|
||||||
|
strlcpy(spaninfo.location, s->parent->location,
|
||||||
sizeof(spaninfo.location));
|
sizeof(spaninfo.location));
|
||||||
|
}
|
||||||
if (s->spantype) {
|
if (s->spantype) {
|
||||||
strlcpy(spaninfo.spantype, s->spantype,
|
strlcpy(spaninfo.spantype, s->spantype,
|
||||||
sizeof(spaninfo.spantype));
|
sizeof(spaninfo.spantype));
|
||||||
@ -4328,20 +4336,17 @@ static int dahdi_ioctl_spanstat_v1(struct file *file, unsigned long data)
|
|||||||
dahdi_lboname(s->lbo),
|
dahdi_lboname(s->lbo),
|
||||||
sizeof(spaninfo_v1.lboname));
|
sizeof(spaninfo_v1.lboname));
|
||||||
|
|
||||||
if (s->manufacturer) {
|
if (s->parent->manufacturer) {
|
||||||
strlcpy(spaninfo_v1.manufacturer,
|
strlcpy(spaninfo_v1.manufacturer, s->parent->manufacturer,
|
||||||
s->manufacturer,
|
|
||||||
sizeof(spaninfo_v1.manufacturer));
|
sizeof(spaninfo_v1.manufacturer));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->devicetype) {
|
if (s->parent->devicetype) {
|
||||||
strlcpy(spaninfo_v1.devicetype,
|
strlcpy(spaninfo_v1.devicetype, s->parent->devicetype,
|
||||||
s->devicetype,
|
|
||||||
sizeof(spaninfo_v1.devicetype));
|
sizeof(spaninfo_v1.devicetype));
|
||||||
}
|
}
|
||||||
|
|
||||||
strlcpy(spaninfo_v1.location,
|
strlcpy(spaninfo_v1.location, s->parent->location,
|
||||||
s->location,
|
|
||||||
sizeof(spaninfo_v1.location));
|
sizeof(spaninfo_v1.location));
|
||||||
|
|
||||||
if (s->spantype) {
|
if (s->spantype) {
|
||||||
@ -5399,7 +5404,7 @@ static int dahdi_ioctl_confdiag(struct file *file, unsigned long data)
|
|||||||
struct pseudo_chan *pseudo;
|
struct pseudo_chan *pseudo;
|
||||||
c = 0;
|
c = 0;
|
||||||
spin_lock_irqsave(&chan_lock, flags);
|
spin_lock_irqsave(&chan_lock, flags);
|
||||||
list_for_each_entry(s, &span_list, node) {
|
list_for_each_entry(s, &span_list, spans_node) {
|
||||||
int k;
|
int k;
|
||||||
for (k = 0; k < s->channels; k++) {
|
for (k = 0; k < s->channels; k++) {
|
||||||
chan = s->chans[k];
|
chan = s->chans[k];
|
||||||
@ -6610,9 +6615,9 @@ static long dahdi_ioctl_compat(struct file *file, unsigned int cmd,
|
|||||||
*/
|
*/
|
||||||
static int _get_next_channo(const struct dahdi_span *span)
|
static int _get_next_channo(const struct dahdi_span *span)
|
||||||
{
|
{
|
||||||
const struct list_head *pos = &span->node;
|
const struct list_head *pos = &span->spans_node;
|
||||||
while (pos != &span_list) {
|
while (pos != &span_list) {
|
||||||
span = list_entry(pos, struct dahdi_span, node);
|
span = list_entry(pos, struct dahdi_span, spans_node);
|
||||||
if (span->channels)
|
if (span->channels)
|
||||||
return span->chans[0]->channo;
|
return span->chans[0]->channo;
|
||||||
pos = pos->next;
|
pos = pos->next;
|
||||||
@ -6636,10 +6641,10 @@ static struct list_head *_find_spanno_and_channo(const struct dahdi_span *span,
|
|||||||
*spanno = 1;
|
*spanno = 1;
|
||||||
*channo = 1;
|
*channo = 1;
|
||||||
|
|
||||||
list_for_each_entry(pos, &span_list, node) {
|
list_for_each_entry(pos, &span_list, spans_node) {
|
||||||
bool skip_span;
|
bool skip_span;
|
||||||
|
|
||||||
loc = &pos->node;
|
loc = &pos->spans_node;
|
||||||
next_channo = _get_next_channo(pos);
|
next_channo = _get_next_channo(pos);
|
||||||
|
|
||||||
skip_span = (pos->spanno == *spanno) ||
|
skip_span = (pos->spanno == *spanno) ||
|
||||||
@ -6658,13 +6663,39 @@ static struct list_head *_find_spanno_and_channo(const struct dahdi_span *span,
|
|||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct dahdi_device *dahdi_create_device(void)
|
||||||
|
{
|
||||||
|
struct dahdi_device *ddev;
|
||||||
|
ddev = kzalloc(sizeof(*ddev), GFP_KERNEL);
|
||||||
|
if (!ddev)
|
||||||
|
return NULL;
|
||||||
|
return ddev;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dahdi_create_device);
|
||||||
|
|
||||||
|
void dahdi_free_device(struct dahdi_device *ddev)
|
||||||
|
{
|
||||||
|
kfree(ddev);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dahdi_free_device);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _dahdi_register - Register the span.
|
* _dahdi_register_span() - Register a new DAHDI span
|
||||||
|
* @span: the DAHDI span
|
||||||
|
* @prefmaster: will the new span be preferred as a master?
|
||||||
*
|
*
|
||||||
* NOTE: Must be called with the registration_mutex held.
|
* Registers a span for usage with DAHDI. All the channel numbers in it
|
||||||
|
* will get the lowest available channel numbers.
|
||||||
|
*
|
||||||
|
* If prefmaster is set to anything > 0, span will attempt to become the
|
||||||
|
* master DAHDI span at registration time. If 0: it will only become
|
||||||
|
* master if no other span is currently the master (i.e.: it is the
|
||||||
|
* first one).
|
||||||
|
*
|
||||||
|
* Must be called with registration_mutex held.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int _dahdi_register(struct dahdi_span *span, int prefmaster)
|
static int _dahdi_register_span(struct dahdi_span *span, int prefmaster)
|
||||||
{
|
{
|
||||||
unsigned int spanno;
|
unsigned int spanno;
|
||||||
unsigned int x;
|
unsigned int x;
|
||||||
@ -6689,7 +6720,7 @@ static int _dahdi_register(struct dahdi_span *span, int prefmaster)
|
|||||||
span->deflaw = DAHDI_LAW_MULAW;
|
span->deflaw = DAHDI_LAW_MULAW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&span->spans_node);
|
||||||
spin_lock_init(&span->lock);
|
spin_lock_init(&span->lock);
|
||||||
|
|
||||||
/* Look through the span list to find the first available span number.
|
/* Look through the span list to find the first available span number.
|
||||||
@ -6735,9 +6766,9 @@ static int _dahdi_register(struct dahdi_span *span, int prefmaster)
|
|||||||
|
|
||||||
spin_lock_irqsave(&chan_lock, flags);
|
spin_lock_irqsave(&chan_lock, flags);
|
||||||
if (loc == &span_list)
|
if (loc == &span_list)
|
||||||
list_add_tail(&span->node, &span_list);
|
list_add_tail(&span->spans_node, &span_list);
|
||||||
else
|
else
|
||||||
list_add(&span->node, loc);
|
list_add(&span->spans_node, loc);
|
||||||
spin_unlock_irqrestore(&chan_lock, flags);
|
spin_unlock_irqrestore(&chan_lock, flags);
|
||||||
set_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
|
set_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
|
||||||
__dahdi_find_master_span();
|
__dahdi_find_master_span();
|
||||||
@ -6762,30 +6793,71 @@ cleanup:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *UNKNOWN = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dahdi_register() - unregister a new DAHDI span
|
* _dahdi_register_device - Registers the spans of a DAHDI device.
|
||||||
* @span: the DAHDI span
|
* @ddev: the DAHDI device
|
||||||
* @prefmaster: will the new span be preferred as a master?
|
|
||||||
*
|
*
|
||||||
* Registers a span for usage with DAHDI. All the channel numbers in it
|
* If pinned_spans is defined add the device to the device list and wait for
|
||||||
* will get the lowest available channel numbers.
|
* userspace to finish registration. Otherwise, go ahead and register the
|
||||||
|
* spans in order as was done historically since the beginning of the zaptel
|
||||||
|
* days.
|
||||||
*
|
*
|
||||||
* If prefmaster is set to anything > 0, span will attempt to become the
|
* Must hold registration_mutex when this function is called.
|
||||||
* master DAHDI span at registration time. If 0: it will only become
|
|
||||||
* master if no other span is currently the master (i.e.: it is the
|
|
||||||
* first one).
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int dahdi_register(struct dahdi_span *span, int prefmaster)
|
static int _dahdi_register_device(struct dahdi_device *ddev,
|
||||||
|
struct device *parent)
|
||||||
{
|
{
|
||||||
int ret;
|
struct dahdi_span *s;
|
||||||
mutex_lock(®istration_mutex);
|
int ret = 0;
|
||||||
ret = _dahdi_register(span, prefmaster);
|
|
||||||
mutex_unlock(®istration_mutex);
|
ddev->manufacturer = (ddev->manufacturer) ?: UNKNOWN;
|
||||||
|
ddev->location = (ddev->location) ?: UNKNOWN;
|
||||||
|
ddev->devicetype = (ddev->devicetype) ?: UNKNOWN;
|
||||||
|
|
||||||
|
list_for_each_entry(s, &ddev->spans, device_node) {
|
||||||
|
s->parent = ddev;
|
||||||
|
ret = _dahdi_register_span(s, 1);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _dahdi_unregister(struct dahdi_span *span)
|
/**
|
||||||
|
* dahdi_register_device() - unregister a new DAHDI device
|
||||||
|
* @ddev: the DAHDI device
|
||||||
|
*
|
||||||
|
* Registers a device for usage with DAHDI.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int dahdi_register_device(struct dahdi_device *ddev, struct device *parent)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!ddev)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(®istration_mutex);
|
||||||
|
ret = _dahdi_register_device(ddev, parent);
|
||||||
|
mutex_unlock(®istration_mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dahdi_register_device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _dahdi_unregister_span() - unregister a DAHDI span
|
||||||
|
* @span: the DAHDI span
|
||||||
|
*
|
||||||
|
* Unregisters a span that has been previously registered with
|
||||||
|
* dahdi_register_span().
|
||||||
|
*
|
||||||
|
* Must be called with the registration_mutex held.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int _dahdi_unregister_span(struct dahdi_span *span)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
struct dahdi_span *new_master, *s;
|
struct dahdi_span *new_master, *s;
|
||||||
@ -6797,7 +6869,7 @@ static int _dahdi_unregister(struct dahdi_span *span)
|
|||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&chan_lock, flags);
|
spin_lock_irqsave(&chan_lock, flags);
|
||||||
list_del_init(&span->node);
|
list_del_init(&span->spans_node);
|
||||||
spin_unlock_irqrestore(&chan_lock, flags);
|
spin_unlock_irqrestore(&chan_lock, flags);
|
||||||
span->spanno = 0;
|
span->spanno = 0;
|
||||||
clear_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
|
clear_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
|
||||||
@ -6822,7 +6894,7 @@ static int _dahdi_unregister(struct dahdi_span *span)
|
|||||||
new_master = NULL;
|
new_master = NULL;
|
||||||
|
|
||||||
spin_lock_irqsave(&chan_lock, flags);
|
spin_lock_irqsave(&chan_lock, flags);
|
||||||
list_for_each_entry(s, &span_list, node) {
|
list_for_each_entry(s, &span_list, spans_node) {
|
||||||
if ((s == new_master) || !can_provide_timing(s))
|
if ((s == new_master) || !can_provide_timing(s))
|
||||||
continue;
|
continue;
|
||||||
new_master = s;
|
new_master = s;
|
||||||
@ -6839,21 +6911,45 @@ static int _dahdi_unregister(struct dahdi_span *span)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dahdi_unregister_span(struct dahdi_span *span)
|
||||||
|
{
|
||||||
|
module_printk(KERN_NOTICE, "%s: %s\n", __func__, span->name);
|
||||||
|
mutex_lock(®istration_mutex);
|
||||||
|
_dahdi_unregister_span(span);
|
||||||
|
list_del_init(&span->device_node);
|
||||||
|
mutex_unlock(®istration_mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dahdi_unregister() - unregister a DAHDI span
|
* dahdi_unregister_device() - unregister a DAHDI device
|
||||||
* @span: the DAHDI span
|
* @span: the DAHDI span
|
||||||
*
|
*
|
||||||
* Unregisters a span that has been previously registered with
|
* Unregisters a device that has been previously registered with
|
||||||
* dahdi_register().
|
* dahdi_register_device().
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
int dahdi_unregister(struct dahdi_span *span)
|
void dahdi_unregister_device(struct dahdi_device *ddev)
|
||||||
{
|
{
|
||||||
int ret;
|
struct dahdi_span *s;
|
||||||
|
WARN_ON(!ddev);
|
||||||
|
might_sleep();
|
||||||
|
if (unlikely(!ddev))
|
||||||
|
return;
|
||||||
|
|
||||||
mutex_lock(®istration_mutex);
|
mutex_lock(®istration_mutex);
|
||||||
ret = _dahdi_unregister(span);
|
list_for_each_entry(s, &ddev->spans, device_node)
|
||||||
|
_dahdi_unregister_span(s);
|
||||||
mutex_unlock(®istration_mutex);
|
mutex_unlock(®istration_mutex);
|
||||||
return ret;
|
|
||||||
|
if (UNKNOWN == ddev->location)
|
||||||
|
ddev->location = NULL;
|
||||||
|
if (UNKNOWN == ddev->manufacturer)
|
||||||
|
ddev->manufacturer = NULL;
|
||||||
|
if (UNKNOWN == ddev->devicetype)
|
||||||
|
ddev->devicetype = NULL;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(dahdi_unregister_device);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This routine converts from linear to ulaw
|
** This routine converts from linear to ulaw
|
||||||
@ -9152,7 +9248,7 @@ static void _process_masterspan(void)
|
|||||||
/* Process any timers */
|
/* Process any timers */
|
||||||
process_timers();
|
process_timers();
|
||||||
|
|
||||||
list_for_each_entry(s, &span_list, node) {
|
list_for_each_entry(s, &span_list, spans_node) {
|
||||||
for (x = 0; x < s->channels; ++x) {
|
for (x = 0; x < s->channels; ++x) {
|
||||||
struct dahdi_chan *const chan = s->chans[x];
|
struct dahdi_chan *const chan = s->chans[x];
|
||||||
if (!chan->confmode)
|
if (!chan->confmode)
|
||||||
@ -9181,7 +9277,7 @@ static void _process_masterspan(void)
|
|||||||
pseudo_rx_audio(&pseudo->chan);
|
pseudo_rx_audio(&pseudo->chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(s, &span_list, node) {
|
list_for_each_entry(s, &span_list, spans_node) {
|
||||||
for (x = 0; x < s->channels; x++) {
|
for (x = 0; x < s->channels; x++) {
|
||||||
struct dahdi_chan *const chan = s->chans[x];
|
struct dahdi_chan *const chan = s->chans[x];
|
||||||
if (!chan->confmode)
|
if (!chan->confmode)
|
||||||
@ -9452,6 +9548,11 @@ MODULE_PARM_DESC(max_pseudo_channels, "Maximum number of pseudo channels.");
|
|||||||
module_param(hwec_overrides_swec, int, 0644);
|
module_param(hwec_overrides_swec, int, 0644);
|
||||||
MODULE_PARM_DESC(hwec_overrides_swec, "When true, a hardware echo canceller is used instead of configured SWEC.");
|
MODULE_PARM_DESC(hwec_overrides_swec, "When true, a hardware echo canceller is used instead of configured SWEC.");
|
||||||
|
|
||||||
|
module_param(pinned_spans, int, 0644);
|
||||||
|
MODULE_PARM_DESC(pinned_spans, "If 1, span/channel numbers can be statically "
|
||||||
|
"defined. If 0, spans/channels are numbered in first come "
|
||||||
|
"first serve order. Default 1");
|
||||||
|
|
||||||
static const struct file_operations dahdi_fops = {
|
static const struct file_operations dahdi_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.open = dahdi_open,
|
.open = dahdi_open,
|
||||||
@ -9494,7 +9595,7 @@ static void watchdog_check(unsigned long ignored)
|
|||||||
struct dahdi_span *s;
|
struct dahdi_span *s;
|
||||||
|
|
||||||
spin_lock_irqsave(&span_list_lock, flags);
|
spin_lock_irqsave(&span_list_lock, flags);
|
||||||
list_for_each_entry(s, &span_list, node) {
|
list_for_each_entry(s, &span_list, spans_node) {
|
||||||
if (s->flags & DAHDI_FLAG_RUNNING) {
|
if (s->flags & DAHDI_FLAG_RUNNING) {
|
||||||
if (s->watchcounter == DAHDI_WATCHDOG_INIT) {
|
if (s->watchcounter == DAHDI_WATCHDOG_INIT) {
|
||||||
/* Whoops, dead card */
|
/* Whoops, dead card */
|
||||||
|
@ -400,6 +400,7 @@ static void dahdi_dynamic_release(struct kref *kref)
|
|||||||
for (x = 0; x < d->span.channels; x++)
|
for (x = 0; x < d->span.channels; x++)
|
||||||
kfree(d->chans[x]);
|
kfree(d->chans[x]);
|
||||||
|
|
||||||
|
dahdi_free_device(d->ddev);
|
||||||
kfree(d);
|
kfree(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,7 +470,7 @@ static int _destroy_dynamic(struct dahdi_dynamic_span *dds)
|
|||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
dahdi_unregister(&d->span);
|
dahdi_unregister_device(d->ddev);
|
||||||
|
|
||||||
spin_lock_irqsave(&dspan_lock, flags);
|
spin_lock_irqsave(&dspan_lock, flags);
|
||||||
list_del_rcu(&d->list);
|
list_del_rcu(&d->list);
|
||||||
@ -578,8 +579,8 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
|
|||||||
d = kzalloc(sizeof(*d), GFP_KERNEL);
|
d = kzalloc(sizeof(*d), GFP_KERNEL);
|
||||||
if (!d)
|
if (!d)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
kref_init(&d->kref);
|
kref_init(&d->kref);
|
||||||
|
d->ddev = dahdi_create_device();
|
||||||
|
|
||||||
for (x = 0; x < dds->numchans; x++) {
|
for (x = 0; x < dds->numchans; x++) {
|
||||||
d->chans[x] = kzalloc(sizeof(*d->chans[x]), GFP_KERNEL);
|
d->chans[x] = kzalloc(sizeof(*d->chans[x]), GFP_KERNEL);
|
||||||
@ -657,8 +658,9 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_add_tail(&d->span.device_node, &d->ddev->spans);
|
||||||
/* Whee! We're created. Now register the span */
|
/* Whee! We're created. Now register the span */
|
||||||
if (dahdi_register(&d->span, 0)) {
|
if (dahdi_register_device(d->ddev, d->dev)) {
|
||||||
printk(KERN_NOTICE "Unable to register span '%s'\n",
|
printk(KERN_NOTICE "Unable to register span '%s'\n",
|
||||||
d->span.name);
|
d->span.name);
|
||||||
dynamic_put(d);
|
dynamic_put(d);
|
||||||
@ -769,7 +771,7 @@ void dahdi_dynamic_unregister_driver(struct dahdi_dynamic_driver *dri)
|
|||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dahdi_unregister(&d->span);
|
dahdi_unregister_device(d->ddev);
|
||||||
spin_lock_irqsave(&dspan_lock, flags);
|
spin_lock_irqsave(&dspan_lock, flags);
|
||||||
list_del_rcu(&d->list);
|
list_del_rcu(&d->list);
|
||||||
spin_unlock_irqrestore(&dspan_lock, flags);
|
spin_unlock_irqrestore(&dspan_lock, flags);
|
||||||
|
@ -146,6 +146,7 @@ struct encdec
|
|||||||
|
|
||||||
struct pciradio {
|
struct pciradio {
|
||||||
struct pci_dev *dev;
|
struct pci_dev *dev;
|
||||||
|
struct dahdi_device *ddev;
|
||||||
struct dahdi_span span;
|
struct dahdi_span span;
|
||||||
unsigned char ios;
|
unsigned char ios;
|
||||||
int usecount;
|
int usecount;
|
||||||
@ -1488,7 +1489,7 @@ static int pciradio_initialize(struct pciradio *rad)
|
|||||||
rad->span.flags = DAHDI_FLAG_RBS;
|
rad->span.flags = DAHDI_FLAG_RBS;
|
||||||
rad->span.ops = &pciradio_span_ops;
|
rad->span.ops = &pciradio_span_ops;
|
||||||
|
|
||||||
if (dahdi_register(&rad->span, 0)) {
|
if (dahdi_register_device(rad->ddev, &rad->dev->dev)) {
|
||||||
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1777,7 +1778,7 @@ static int __devinit pciradio_init_one(struct pci_dev *pdev, const struct pci_de
|
|||||||
release_region(rad->ioaddr, 0xff);
|
release_region(rad->ioaddr, 0xff);
|
||||||
pci_free_consistent(pdev, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma);
|
pci_free_consistent(pdev, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma);
|
||||||
pci_set_drvdata(pdev, NULL);
|
pci_set_drvdata(pdev, NULL);
|
||||||
dahdi_unregister(&rad->span);
|
dahdi_free_device(rad->ddev);
|
||||||
kfree(rad);
|
kfree(rad);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
@ -1810,7 +1811,7 @@ static int __devinit pciradio_init_one(struct pci_dev *pdev, const struct pci_de
|
|||||||
|
|
||||||
static void pciradio_release(struct pciradio *rad)
|
static void pciradio_release(struct pciradio *rad)
|
||||||
{
|
{
|
||||||
dahdi_unregister(&rad->span);
|
dahdi_unregister_device(rad->ddev);
|
||||||
if (rad->freeregion)
|
if (rad->freeregion)
|
||||||
release_region(rad->ioaddr, 0xff);
|
release_region(rad->ioaddr, 0xff);
|
||||||
kfree(rad);
|
kfree(rad);
|
||||||
|
@ -97,6 +97,7 @@ struct tor2 {
|
|||||||
unsigned long xilinx8_region; /* 8 bit Region allocated to Xilinx */
|
unsigned long xilinx8_region; /* 8 bit Region allocated to Xilinx */
|
||||||
unsigned long xilinx8_len; /* Length of 8 bit Xilinx region */
|
unsigned long xilinx8_len; /* Length of 8 bit Xilinx region */
|
||||||
__iomem volatile unsigned char *mem8; /* Virtual representation of 8 bit Xilinx memory area */
|
__iomem volatile unsigned char *mem8; /* Virtual representation of 8 bit Xilinx memory area */
|
||||||
|
struct dahdi_device *ddev;
|
||||||
struct tor2_span tspans[SPANS_PER_CARD]; /* Span data */
|
struct tor2_span tspans[SPANS_PER_CARD]; /* Span data */
|
||||||
struct dahdi_chan **chans[SPANS_PER_CARD]; /* Pointers to card channels */
|
struct dahdi_chan **chans[SPANS_PER_CARD]; /* Pointers to card channels */
|
||||||
struct tor2_chan tchans[32 * SPANS_PER_CARD]; /* Channel user data */
|
struct tor2_chan tchans[32 * SPANS_PER_CARD]; /* Channel user data */
|
||||||
@ -285,10 +286,6 @@ static void init_spans(struct tor2 *tor)
|
|||||||
snprintf(s->desc, sizeof(s->desc) - 1,
|
snprintf(s->desc, sizeof(s->desc) - 1,
|
||||||
"Tormenta 2 (PCI) Quad %s Card %d Span %d",
|
"Tormenta 2 (PCI) Quad %s Card %d Span %d",
|
||||||
(tor->cardtype == TYPE_T1) ? "T1" : "E1", tor->num, x + 1);
|
(tor->cardtype == TYPE_T1) ? "T1" : "E1", tor->num, x + 1);
|
||||||
s->manufacturer = "Digium";
|
|
||||||
strlcpy(s->devicetype, tor->type, sizeof(s->devicetype));
|
|
||||||
snprintf(s->location, sizeof(s->location) - 1,
|
|
||||||
"PCI Bus %02d Slot %02d", tor->pci->bus->number, PCI_SLOT(tor->pci->devfn) + 1);
|
|
||||||
if (tor->cardtype == TYPE_T1) {
|
if (tor->cardtype == TYPE_T1) {
|
||||||
s->channels = 24;
|
s->channels = 24;
|
||||||
s->deflaw = DAHDI_LAW_MULAW;
|
s->deflaw = DAHDI_LAW_MULAW;
|
||||||
@ -322,19 +319,31 @@ static void init_spans(struct tor2 *tor)
|
|||||||
|
|
||||||
static int __devinit tor2_launch(struct tor2 *tor)
|
static int __devinit tor2_launch(struct tor2 *tor)
|
||||||
{
|
{
|
||||||
|
int res;
|
||||||
struct dahdi_span *s;
|
struct dahdi_span *s;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &tor->tspans[0].dahdi_span.flags))
|
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &tor->tspans[0].dahdi_span.flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
tor->ddev = dahdi_create_device();
|
||||||
|
tor->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
|
||||||
|
tor->pci->bus->number,
|
||||||
|
PCI_SLOT(tor->pci->devfn) + 1);
|
||||||
|
|
||||||
|
if (!tor->ddev->location)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
printk(KERN_INFO "Tor2: Launching card: %d\n", tor->order);
|
printk(KERN_INFO "Tor2: Launching card: %d\n", tor->order);
|
||||||
for (i = 0; i < SPANS_PER_CARD; ++i) {
|
for (i = 0; i < SPANS_PER_CARD; ++i) {
|
||||||
s = &tor->tspans[i].dahdi_span;
|
s = &tor->tspans[i].dahdi_span;
|
||||||
if (dahdi_register(s, 0)) {
|
list_add_tail(&s->device_node, &tor->ddev->spans);
|
||||||
printk(KERN_ERR "Unable to register span %s\n", s->name);
|
|
||||||
goto error_exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res = dahdi_register_device(tor->ddev, &tor->pci->dev);
|
||||||
|
if (res) {
|
||||||
|
dev_err(&tor->pci->dev, "Unable to register with DAHDI.\n");
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
writew(PLX_INTENA, &tor->plx[INTCSR]); /* enable PLX interrupt */
|
writew(PLX_INTENA, &tor->plx[INTCSR]); /* enable PLX interrupt */
|
||||||
|
|
||||||
@ -342,14 +351,6 @@ static int __devinit tor2_launch(struct tor2 *tor)
|
|||||||
tasklet_init(&tor->tor2_tlet, tor2_tasklet, (unsigned long)tor);
|
tasklet_init(&tor->tor2_tlet, tor2_tasklet, (unsigned long)tor);
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_exit:
|
|
||||||
for (i = 0; i < SPANS_PER_CARD; ++i) {
|
|
||||||
s = &tor->tspans[i].dahdi_span;
|
|
||||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags))
|
|
||||||
dahdi_unregister(s);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_tor(struct tor2 *tor)
|
static void free_tor(struct tor2 *tor)
|
||||||
@ -365,6 +366,8 @@ static void free_tor(struct tor2 *tor)
|
|||||||
if (tor->chans[x])
|
if (tor->chans[x])
|
||||||
kfree(tor->chans[x]);
|
kfree(tor->chans[x]);
|
||||||
}
|
}
|
||||||
|
kfree(tor->ddev->location);
|
||||||
|
dahdi_free_device(tor->ddev);
|
||||||
kfree(tor);
|
kfree(tor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,7 +634,6 @@ static struct pci_driver tor2_driver;
|
|||||||
static void __devexit tor2_remove(struct pci_dev *pdev)
|
static void __devexit tor2_remove(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
struct tor2 *tor;
|
struct tor2 *tor;
|
||||||
int i;
|
|
||||||
|
|
||||||
tor = pci_get_drvdata(pdev);
|
tor = pci_get_drvdata(pdev);
|
||||||
if (!tor)
|
if (!tor)
|
||||||
@ -641,11 +643,7 @@ static void __devexit tor2_remove(struct pci_dev *pdev)
|
|||||||
writeb(0, &tor->mem8[LEDREG]);
|
writeb(0, &tor->mem8[LEDREG]);
|
||||||
writew(0, &tor->plx[INTCSR]);
|
writew(0, &tor->plx[INTCSR]);
|
||||||
free_irq(tor->irq, tor);
|
free_irq(tor->irq, tor);
|
||||||
for (i = 0; i < SPANS_PER_CARD; ++i) {
|
dahdi_unregister_device(tor->ddev);
|
||||||
struct dahdi_span *s = &tor->tspans[i].dahdi_span;
|
|
||||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags))
|
|
||||||
dahdi_unregister(s);
|
|
||||||
}
|
|
||||||
release_mem_region(tor->plx_region, tor->plx_len);
|
release_mem_region(tor->plx_region, tor->plx_len);
|
||||||
release_mem_region(tor->xilinx32_region, tor->xilinx32_len);
|
release_mem_region(tor->xilinx32_region, tor->xilinx32_len);
|
||||||
release_mem_region(tor->xilinx8_region, tor->xilinx8_len);
|
release_mem_region(tor->xilinx8_region, tor->xilinx8_len);
|
||||||
|
@ -2030,7 +2030,7 @@ static int __init voicebus_module_init(void)
|
|||||||
* defined, but it will make sure that this module is a dependency of
|
* defined, but it will make sure that this module is a dependency of
|
||||||
* dahdi.ko, so that when it is being unloded, this module will be
|
* dahdi.ko, so that when it is being unloded, this module will be
|
||||||
* unloaded as well. */
|
* unloaded as well. */
|
||||||
dahdi_register(NULL, 0);
|
dahdi_register_device(NULL, NULL);
|
||||||
spin_lock_init(&loader_list_lock);
|
spin_lock_init(&loader_list_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2494,11 +2494,6 @@ static void init_spans(struct b4xxp *b4)
|
|||||||
|
|
||||||
sprintf(bspan->span.name, "B4/%d/%d", b4->cardno, i+1);
|
sprintf(bspan->span.name, "B4/%d/%d", b4->cardno, i+1);
|
||||||
sprintf(bspan->span.desc, "B4XXP (PCI) Card %d Span %d", b4->cardno, i+1);
|
sprintf(bspan->span.desc, "B4XXP (PCI) Card %d Span %d", b4->cardno, i+1);
|
||||||
bspan->span.manufacturer = "Digium";
|
|
||||||
strlcpy(bspan->span.devicetype, b4->variety,
|
|
||||||
sizeof(bspan->span.devicetype));
|
|
||||||
sprintf(bspan->span.location, "PCI Bus %02d Slot %02d",
|
|
||||||
b4->pdev->bus->number, PCI_SLOT(b4->pdev->devfn) + 1);
|
|
||||||
|
|
||||||
bspan->span.ops = &b4xxp_span_ops;
|
bspan->span.ops = &b4xxp_span_ops;
|
||||||
/* HDLC stuff */
|
/* HDLC stuff */
|
||||||
@ -2930,14 +2925,27 @@ static int __devinit b4xx_probe(struct pci_dev *pdev, const struct pci_device_id
|
|||||||
hfc_init_all_st(b4);
|
hfc_init_all_st(b4);
|
||||||
|
|
||||||
/* initialize the DAHDI structures, and let DAHDI know it has some new hardware to play with */
|
/* initialize the DAHDI structures, and let DAHDI know it has some new hardware to play with */
|
||||||
|
b4->ddev = dahdi_create_device();
|
||||||
init_spans(b4);
|
init_spans(b4);
|
||||||
|
|
||||||
for (x=0; x < b4->numspans; x++) {
|
for (x=0; x < b4->numspans; x++) {
|
||||||
if (dahdi_register(&b4->spans[x].span, 0)) {
|
struct dahdi_span *const s = &b4->spans[x].span;
|
||||||
dev_err(&b4->pdev->dev,
|
list_add_tail(&s->device_node, &b4->ddev->spans);
|
||||||
"Unable to register span %s\n",
|
|
||||||
b4->spans[x].span.name);
|
|
||||||
goto err_out_unreg_spans;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b4->ddev->manufacturer = "Digium";
|
||||||
|
b4->ddev->devicetype = b4->variety;
|
||||||
|
b4->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
|
||||||
|
b4->pdev->bus->number,
|
||||||
|
PCI_SLOT(b4->pdev->devfn) + 1);
|
||||||
|
if (!b4->ddev->location) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err_out_del_from_card_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dahdi_register_device(b4->ddev, &b4->pdev->dev)) {
|
||||||
|
dev_err(&b4->pdev->dev, "Unable to register device.\n");
|
||||||
|
goto err_out_unreg_spans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2973,10 +2981,7 @@ static int __devinit b4xx_probe(struct pci_dev *pdev, const struct pci_device_id
|
|||||||
|
|
||||||
/* 'x' will have the failing span #. (0-3). We need to unregister everything before it. */
|
/* 'x' will have the failing span #. (0-3). We need to unregister everything before it. */
|
||||||
err_out_unreg_spans:
|
err_out_unreg_spans:
|
||||||
while (x) {
|
dahdi_unregister_device(b4->ddev);
|
||||||
dahdi_unregister(&b4->spans[x].span);
|
|
||||||
x--;
|
|
||||||
};
|
|
||||||
|
|
||||||
b4xxp_init_stage1(b4); /* full reset, re-init to "no-irq" state */
|
b4xxp_init_stage1(b4); /* full reset, re-init to "no-irq" state */
|
||||||
free_irq(pdev->irq, b4);
|
free_irq(pdev->irq, b4);
|
||||||
@ -2997,6 +3002,8 @@ err_out_free_mem:
|
|||||||
pci_set_drvdata(pdev, NULL);
|
pci_set_drvdata(pdev, NULL);
|
||||||
pci_iounmap(pdev, b4->ioaddr);
|
pci_iounmap(pdev, b4->ioaddr);
|
||||||
pci_iounmap(pdev, b4->addr);
|
pci_iounmap(pdev, b4->addr);
|
||||||
|
kfree(b4->ddev->location);
|
||||||
|
dahdi_free_device(b4->ddev);
|
||||||
kfree(b4);
|
kfree(b4);
|
||||||
|
|
||||||
err_out_release_regions:
|
err_out_release_regions:
|
||||||
@ -3011,14 +3018,11 @@ err_out_disable_pdev:
|
|||||||
static void __devexit b4xxp_remove(struct pci_dev *pdev)
|
static void __devexit b4xxp_remove(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
struct b4xxp *b4 = pci_get_drvdata(pdev);
|
struct b4xxp *b4 = pci_get_drvdata(pdev);
|
||||||
int i;
|
|
||||||
|
|
||||||
if (b4) {
|
if (b4) {
|
||||||
b4->shutdown = 1;
|
b4->shutdown = 1;
|
||||||
|
|
||||||
for (i=b4->numspans - 1; i >= 0; i--) {
|
dahdi_unregister_device(b4->ddev);
|
||||||
dahdi_unregister(&b4->spans[i].span);
|
|
||||||
}
|
|
||||||
|
|
||||||
b4xxp_init_stage1(b4);
|
b4xxp_init_stage1(b4);
|
||||||
remove_sysfs_files(b4);
|
remove_sysfs_files(b4);
|
||||||
@ -3033,6 +3037,8 @@ static void __devexit b4xxp_remove(struct pci_dev *pdev)
|
|||||||
|
|
||||||
tasklet_kill(&b4->b4xxp_tlet);
|
tasklet_kill(&b4->b4xxp_tlet);
|
||||||
|
|
||||||
|
kfree(b4->ddev->location);
|
||||||
|
dahdi_free_device(b4->ddev);
|
||||||
kfree(b4);
|
kfree(b4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,6 +474,7 @@ struct b4xxp {
|
|||||||
/* Flags for our bottom half */
|
/* Flags for our bottom half */
|
||||||
unsigned int shutdown; /* 1=bottom half doesn't process anything, just returns */
|
unsigned int shutdown; /* 1=bottom half doesn't process anything, just returns */
|
||||||
struct tasklet_struct b4xxp_tlet;
|
struct tasklet_struct b4xxp_tlet;
|
||||||
|
struct dahdi_device *ddev;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* CPLD access bits */
|
/* CPLD access bits */
|
||||||
|
@ -135,6 +135,7 @@ static int wecareregs[] =
|
|||||||
struct wcfxo {
|
struct wcfxo {
|
||||||
struct pci_dev *dev;
|
struct pci_dev *dev;
|
||||||
char *variety;
|
char *variety;
|
||||||
|
struct dahdi_device *ddev;
|
||||||
struct dahdi_span span;
|
struct dahdi_span span;
|
||||||
struct dahdi_chan _chan;
|
struct dahdi_chan _chan;
|
||||||
struct dahdi_chan *chan;
|
struct dahdi_chan *chan;
|
||||||
@ -647,14 +648,20 @@ static const struct dahdi_span_ops wcfxo_span_ops = {
|
|||||||
|
|
||||||
static int wcfxo_initialize(struct wcfxo *wc)
|
static int wcfxo_initialize(struct wcfxo *wc)
|
||||||
{
|
{
|
||||||
|
wc->ddev = dahdi_create_device();
|
||||||
|
|
||||||
/* DAHDI stuff */
|
/* DAHDI stuff */
|
||||||
sprintf(wc->span.name, "WCFXO/%d", wc->pos);
|
sprintf(wc->span.name, "WCFXO/%d", wc->pos);
|
||||||
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1);
|
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1);
|
||||||
sprintf(wc->chan->name, "WCFXO/%d/%d", wc->pos, 0);
|
sprintf(wc->chan->name, "WCFXO/%d/%d", wc->pos, 0);
|
||||||
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
|
wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
|
||||||
"PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
|
wc->dev->bus->number,
|
||||||
wc->span.manufacturer = "Digium";
|
PCI_SLOT(wc->dev->devfn) + 1);
|
||||||
strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
|
if (!wc->ddev->location)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
wc->ddev->manufacturer = "Digium";
|
||||||
|
wc->ddev->devicetype = wc->variety;
|
||||||
wc->chan->sigcap = DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF;
|
wc->chan->sigcap = DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF;
|
||||||
wc->chan->chanpos = 1;
|
wc->chan->chanpos = 1;
|
||||||
wc->span.chans = &wc->chan;
|
wc->span.chans = &wc->chan;
|
||||||
@ -668,7 +675,8 @@ static int wcfxo_initialize(struct wcfxo *wc)
|
|||||||
|
|
||||||
wc->chan->pvt = wc;
|
wc->chan->pvt = wc;
|
||||||
wc->span.ops = &wcfxo_span_ops;
|
wc->span.ops = &wcfxo_span_ops;
|
||||||
if (dahdi_register(&wc->span, 0)) {
|
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
|
||||||
|
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
|
||||||
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -976,7 +984,7 @@ static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_devic
|
|||||||
printk(KERN_NOTICE "Failed to initailize DAA, giving up...\n");
|
printk(KERN_NOTICE "Failed to initailize DAA, giving up...\n");
|
||||||
wcfxo_stop_dma(wc);
|
wcfxo_stop_dma(wc);
|
||||||
wcfxo_disable_interrupts(wc);
|
wcfxo_disable_interrupts(wc);
|
||||||
dahdi_unregister(&wc->span);
|
dahdi_unregister_device(wc->ddev);
|
||||||
free_irq(pdev->irq, wc);
|
free_irq(pdev->irq, wc);
|
||||||
|
|
||||||
/* Reset PCI chip and registers */
|
/* Reset PCI chip and registers */
|
||||||
@ -984,6 +992,8 @@ static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_devic
|
|||||||
|
|
||||||
if (wc->freeregion)
|
if (wc->freeregion)
|
||||||
release_region(wc->ioaddr, 0xff);
|
release_region(wc->ioaddr, 0xff);
|
||||||
|
kfree(wc->ddev->location);
|
||||||
|
dahdi_free_device(wc->ddev);
|
||||||
kfree(wc);
|
kfree(wc);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
@ -995,9 +1005,11 @@ static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_devic
|
|||||||
|
|
||||||
static void wcfxo_release(struct wcfxo *wc)
|
static void wcfxo_release(struct wcfxo *wc)
|
||||||
{
|
{
|
||||||
dahdi_unregister(&wc->span);
|
dahdi_unregister_device(wc->ddev);
|
||||||
if (wc->freeregion)
|
if (wc->freeregion)
|
||||||
release_region(wc->ioaddr, 0xff);
|
release_region(wc->ioaddr, 0xff);
|
||||||
|
kfree(wc->ddev->location);
|
||||||
|
dahdi_free_device(wc->ddev);
|
||||||
kfree(wc);
|
kfree(wc);
|
||||||
printk(KERN_INFO "Freed a Wildcard\n");
|
printk(KERN_INFO "Freed a Wildcard\n");
|
||||||
}
|
}
|
||||||
|
@ -159,6 +159,7 @@ struct t1xxp {
|
|||||||
unsigned char ec_chunk2[31][DAHDI_CHUNKSIZE];
|
unsigned char ec_chunk2[31][DAHDI_CHUNKSIZE];
|
||||||
unsigned char tempo[32];
|
unsigned char tempo[32];
|
||||||
struct dahdi_span span; /* Span */
|
struct dahdi_span span; /* Span */
|
||||||
|
struct dahdi_device *ddev;
|
||||||
struct dahdi_chan *chans[31]; /* Channels */
|
struct dahdi_chan *chans[31]; /* Channels */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -272,10 +273,11 @@ static void t1xxp_release(struct t1xxp *wc)
|
|||||||
{
|
{
|
||||||
unsigned int x;
|
unsigned int x;
|
||||||
|
|
||||||
dahdi_unregister(&wc->span);
|
dahdi_unregister_device(wc->ddev);
|
||||||
for (x = 0; x < (wc->ise1 ? 31 : 24); x++) {
|
for (x = 0; x < (wc->ise1 ? 31 : 24); x++) {
|
||||||
kfree(wc->chans[x]);
|
kfree(wc->chans[x]);
|
||||||
}
|
}
|
||||||
|
dahdi_free_device(wc->ddev);
|
||||||
kfree(wc);
|
kfree(wc);
|
||||||
printk(KERN_INFO "Freed a Wildcard\n");
|
printk(KERN_INFO "Freed a Wildcard\n");
|
||||||
}
|
}
|
||||||
@ -770,13 +772,20 @@ static int t1xxp_software_init(struct t1xxp *wc)
|
|||||||
}
|
}
|
||||||
if (x >= WC_MAX_CARDS)
|
if (x >= WC_MAX_CARDS)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
wc->ddev = dahdi_create_device();
|
||||||
|
|
||||||
wc->num = x;
|
wc->num = x;
|
||||||
sprintf(wc->span.name, "WCT1/%d", wc->num);
|
sprintf(wc->span.name, "WCT1/%d", wc->num);
|
||||||
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num);
|
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num);
|
||||||
wc->span.manufacturer = "Digium";
|
wc->ddev->manufacturer = "Digium";
|
||||||
strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
|
wc->ddev->devicetype = wc->variety;
|
||||||
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
|
wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
|
||||||
"PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
|
wc->dev->bus->number,
|
||||||
|
PCI_SLOT(wc->dev->devfn) + 1);
|
||||||
|
if (!wc->ddev->location)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
wc->span.irq = wc->dev->irq;
|
wc->span.irq = wc->dev->irq;
|
||||||
wc->span.chans = wc->chans;
|
wc->span.chans = wc->chans;
|
||||||
wc->span.flags = DAHDI_FLAG_RBS;
|
wc->span.flags = DAHDI_FLAG_RBS;
|
||||||
@ -801,7 +810,8 @@ static int t1xxp_software_init(struct t1xxp *wc)
|
|||||||
wc->chans[x]->chanpos = x + 1;
|
wc->chans[x]->chanpos = x + 1;
|
||||||
}
|
}
|
||||||
wc->span.ops = &t1xxp_span_ops;
|
wc->span.ops = &t1xxp_span_ops;
|
||||||
if (dahdi_register(&wc->span, 0)) {
|
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
|
||||||
|
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
|
||||||
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -325,6 +325,7 @@ struct t4 {
|
|||||||
int num; /* Which card we are */
|
int num; /* Which card we are */
|
||||||
int t1e1; /* T1/E1 select pins */
|
int t1e1; /* T1/E1 select pins */
|
||||||
int syncsrc; /* active sync source */
|
int syncsrc; /* active sync source */
|
||||||
|
struct dahdi_device *ddev;
|
||||||
struct t4_span *tspans[4]; /* Individual spans */
|
struct t4_span *tspans[4]; /* Individual spans */
|
||||||
int numspans; /* Number of spans on the card */
|
int numspans; /* Number of spans on the card */
|
||||||
int blinktimer;
|
int blinktimer;
|
||||||
@ -1698,34 +1699,30 @@ static int t4_close(struct dahdi_chan *chan)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VPM_SUPPORT
|
static int set_span_devicetype(struct t4 *wc)
|
||||||
static void set_span_devicetype(struct t4 *wc)
|
|
||||||
{
|
{
|
||||||
int x;
|
#ifdef VPM_SUPPORT
|
||||||
|
const char *vpmstring;
|
||||||
for (x = 0; x < wc->numspans; x++) {
|
|
||||||
struct t4_span *const ts = wc->tspans[x];
|
|
||||||
strlcpy(ts->span.devicetype, wc->devtype->desc,
|
|
||||||
sizeof(ts->span.devicetype));
|
|
||||||
|
|
||||||
if (wc->vpm450m) {
|
if (wc->vpm450m) {
|
||||||
strncat(ts->span.devicetype, (wc->numspans > 2) ? " (VPMOCT128)" : " (VPMOCT064)",
|
if (wc->numspans > 2)
|
||||||
sizeof(ts->span.devicetype) - 1);
|
vpmstring = "OCT128";
|
||||||
}
|
else
|
||||||
}
|
vpmstring = "OCT064";
|
||||||
|
|
||||||
|
wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s (VPM%s)",
|
||||||
|
wc->devtype->desc, vpmstring);
|
||||||
|
} else {
|
||||||
|
wc->ddev->devicetype = kasprintf(GFP_KERNEL, wc->devtype->desc);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void set_span_devicetype(struct t4 *wc)
|
wc->ddev->devicetype = kasprintf(GFP_KERNEL, wc->devtype->desc);
|
||||||
{
|
|
||||||
int x;
|
|
||||||
for (x = 0; x < wc->numspans; x++) {
|
|
||||||
struct t4_span *const ts = wc->tspans[x];
|
|
||||||
strlcpy(ts->span.devicetype, wc->devtype->desc,
|
|
||||||
sizeof(ts->span.devicetype));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!wc->ddev->devicetype)
|
||||||
|
return -ENOMEM;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* The number of cards we have seen with each
|
/* The number of cards we have seen with each
|
||||||
possible 'order' switch setting.
|
possible 'order' switch setting.
|
||||||
*/
|
*/
|
||||||
@ -1805,13 +1802,6 @@ static void init_spans(struct t4 *wc)
|
|||||||
sprintf(ts->span.name, "TE%d/%d/%d", wc->numspans, wc->num, x + 1);
|
sprintf(ts->span.name, "TE%d/%d/%d", wc->numspans, wc->num, x + 1);
|
||||||
snprintf(ts->span.desc, sizeof(ts->span.desc) - 1,
|
snprintf(ts->span.desc, sizeof(ts->span.desc) - 1,
|
||||||
"T%dXXP (PCI) Card %d Span %d", wc->numspans, wc->num, x+1);
|
"T%dXXP (PCI) Card %d Span %d", wc->numspans, wc->num, x+1);
|
||||||
ts->span.manufacturer = "Digium";
|
|
||||||
if (!ignore_rotary && (1 == order_index[wc->order]))
|
|
||||||
snprintf(ts->span.location, sizeof(ts->span.location) - 1, "Board ID Switch %d", wc->order);
|
|
||||||
else
|
|
||||||
snprintf(ts->span.location, sizeof(ts->span.location) - 1,
|
|
||||||
"PCI%s Bus %02d Slot %02d", (ts->spanflags & FLAG_EXPRESS) ? " Express" : " ",
|
|
||||||
wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
|
|
||||||
switch (ts->linemode) {
|
switch (ts->linemode) {
|
||||||
case T1:
|
case T1:
|
||||||
ts->span.spantype = "T1";
|
ts->span.spantype = "T1";
|
||||||
@ -4043,7 +4033,10 @@ static int t4_hardware_init_2(struct t4 *wc)
|
|||||||
|
|
||||||
static int __devinit t4_launch(struct t4 *wc)
|
static int __devinit t4_launch(struct t4 *wc)
|
||||||
{
|
{
|
||||||
|
int x;
|
||||||
|
int res;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &wc->tspans[0]->span.flags))
|
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &wc->tspans[0]->span.flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -4055,35 +4048,33 @@ static int __devinit t4_launch(struct t4 *wc)
|
|||||||
|
|
||||||
t4_serial_setup(wc);
|
t4_serial_setup(wc);
|
||||||
|
|
||||||
if (dahdi_register(&wc->tspans[0]->span, 0)) {
|
wc->ddev->manufacturer = "Digium";
|
||||||
dev_err(&wc->dev->dev, "Unable to register span %s\n",
|
if (!ignore_rotary && (1 == order_index[wc->order])) {
|
||||||
wc->tspans[0]->span.name);
|
wc->ddev->location = kasprintf(GFP_KERNEL,
|
||||||
return -1;
|
"Board ID Switch %d", wc->order);
|
||||||
}
|
} else {
|
||||||
if (dahdi_register(&wc->tspans[1]->span, 0)) {
|
bool express = ((wc->tspans[0]->spanflags & FLAG_EXPRESS) > 0);
|
||||||
dev_err(&wc->dev->dev, "Unable to register span %s\n",
|
wc->ddev->location = kasprintf(GFP_KERNEL,
|
||||||
wc->tspans[1]->span.name);
|
"PCI%s Bus %02d Slot %02d",
|
||||||
dahdi_unregister(&wc->tspans[0]->span);
|
(express) ? " Express" : "",
|
||||||
return -1;
|
wc->dev->bus->number,
|
||||||
|
PCI_SLOT(wc->dev->devfn) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wc->numspans == 4) {
|
if (!wc->ddev->location)
|
||||||
if (dahdi_register(&wc->tspans[2]->span, 0)) {
|
return -ENOMEM;
|
||||||
dev_err(&wc->dev->dev, "Unable to register span %s\n",
|
|
||||||
wc->tspans[2]->span.name);
|
for (x = 0; x < wc->numspans; ++x) {
|
||||||
dahdi_unregister(&wc->tspans[0]->span);
|
list_add_tail(&wc->tspans[x]->span.device_node,
|
||||||
dahdi_unregister(&wc->tspans[1]->span);
|
&wc->ddev->spans);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (dahdi_register(&wc->tspans[3]->span, 0)) {
|
|
||||||
dev_err(&wc->dev->dev, "Unable to register span %s\n",
|
|
||||||
wc->tspans[3]->span.name);
|
|
||||||
dahdi_unregister(&wc->tspans[0]->span);
|
|
||||||
dahdi_unregister(&wc->tspans[1]->span);
|
|
||||||
dahdi_unregister(&wc->tspans[2]->span);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res = dahdi_register_device(wc->ddev, &wc->dev->dev);
|
||||||
|
if (res) {
|
||||||
|
dev_err(&wc->dev->dev, "Failed to register with DAHDI.\n");
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_bit(T4_CHECK_TIMING, &wc->checkflag);
|
set_bit(T4_CHECK_TIMING, &wc->checkflag);
|
||||||
spin_lock_irqsave(&wc->reglock, flags);
|
spin_lock_irqsave(&wc->reglock, flags);
|
||||||
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
|
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
|
||||||
@ -4105,6 +4096,10 @@ static void free_wc(struct t4 *wc)
|
|||||||
}
|
}
|
||||||
kfree(wc->tspans[x]);
|
kfree(wc->tspans[x]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kfree(wc->ddev->devicetype);
|
||||||
|
kfree(wc->ddev->location);
|
||||||
|
dahdi_free_device(wc->ddev);
|
||||||
kfree(wc);
|
kfree(wc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4146,11 +4141,16 @@ static int __devinit t4_init_one(struct pci_dev *pdev, const struct pci_device_i
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(wc = kmalloc(sizeof(*wc), GFP_KERNEL))) {
|
wc = kzalloc(sizeof(*wc), GFP_KERNEL);
|
||||||
|
if (!wc)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
wc->ddev = dahdi_create_device();
|
||||||
|
if (!wc->ddev) {
|
||||||
|
kfree(wc);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(wc, 0x0, sizeof(*wc));
|
|
||||||
spin_lock_init(&wc->reglock);
|
spin_lock_init(&wc->reglock);
|
||||||
wc->devtype = (const struct devtype *)(ent->driver_data);
|
wc->devtype = (const struct devtype *)(ent->driver_data);
|
||||||
|
|
||||||
@ -4355,9 +4355,12 @@ static int t4_hardware_stop(struct t4 *wc)
|
|||||||
|
|
||||||
static void _t4_remove_one(struct t4 *wc)
|
static void _t4_remove_one(struct t4 *wc)
|
||||||
{
|
{
|
||||||
struct dahdi_span *span;
|
|
||||||
int basesize;
|
int basesize;
|
||||||
int i;
|
|
||||||
|
if (!wc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dahdi_unregister_device(wc->ddev);
|
||||||
|
|
||||||
remove_sysfs_files(wc);
|
remove_sysfs_files(wc);
|
||||||
|
|
||||||
@ -4376,11 +4379,6 @@ static void _t4_remove_one(struct t4 *wc)
|
|||||||
if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN))
|
if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN))
|
||||||
basesize = basesize * 2;
|
basesize = basesize * 2;
|
||||||
|
|
||||||
for (i = 0; i < wc->numspans; ++i) {
|
|
||||||
span = &wc->tspans[i]->span;
|
|
||||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags))
|
|
||||||
dahdi_unregister(span);
|
|
||||||
}
|
|
||||||
#ifdef ENABLE_WORKQUEUES
|
#ifdef ENABLE_WORKQUEUES
|
||||||
if (wc->workq) {
|
if (wc->workq) {
|
||||||
flush_workqueue(wc->workq);
|
flush_workqueue(wc->workq);
|
||||||
|
@ -205,6 +205,7 @@ struct wctdm {
|
|||||||
struct pci_dev *dev;
|
struct pci_dev *dev;
|
||||||
char *variety;
|
char *variety;
|
||||||
struct dahdi_span span;
|
struct dahdi_span span;
|
||||||
|
struct dahdi_device *ddev;
|
||||||
unsigned char ios;
|
unsigned char ios;
|
||||||
int usecount;
|
int usecount;
|
||||||
unsigned int intcount;
|
unsigned int intcount;
|
||||||
@ -2362,13 +2363,26 @@ static int wctdm_initialize(struct wctdm *wc)
|
|||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
|
wc->ddev = dahdi_create_device();
|
||||||
|
if (!wc->ddev)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
/* DAHDI stuff */
|
/* DAHDI stuff */
|
||||||
sprintf(wc->span.name, "WCTDM/%d", wc->pos);
|
sprintf(wc->span.name, "WCTDM/%d", wc->pos);
|
||||||
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1);
|
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1);
|
||||||
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
|
wc->ddev->location = kasprintf(GFP_KERNEL,
|
||||||
"PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
|
"PCI Bus %02d Slot %02d",
|
||||||
wc->span.manufacturer = "Digium";
|
wc->dev->bus->number,
|
||||||
strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
|
PCI_SLOT(wc->dev->devfn) + 1);
|
||||||
|
if (!wc->ddev->location) {
|
||||||
|
dahdi_free_device(wc->ddev);
|
||||||
|
wc->ddev = NULL;
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
wc->ddev->manufacturer = "Digium";
|
||||||
|
wc->ddev->devicetype = wc->variety;
|
||||||
|
|
||||||
if (alawoverride) {
|
if (alawoverride) {
|
||||||
printk(KERN_INFO "ALAW override parameter detected. Device will be operating in ALAW\n");
|
printk(KERN_INFO "ALAW override parameter detected. Device will be operating in ALAW\n");
|
||||||
wc->span.deflaw = DAHDI_LAW_ALAW;
|
wc->span.deflaw = DAHDI_LAW_ALAW;
|
||||||
@ -2388,8 +2402,12 @@ static int wctdm_initialize(struct wctdm *wc)
|
|||||||
wc->span.flags = DAHDI_FLAG_RBS;
|
wc->span.flags = DAHDI_FLAG_RBS;
|
||||||
wc->span.ops = &wctdm_span_ops;
|
wc->span.ops = &wctdm_span_ops;
|
||||||
|
|
||||||
if (dahdi_register(&wc->span, 0)) {
|
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
|
||||||
|
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
|
||||||
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
||||||
|
kfree(wc->ddev->location);
|
||||||
|
dahdi_free_device(wc->ddev);
|
||||||
|
wc->ddev = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -2677,7 +2695,9 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
|
|||||||
release_region(wc->ioaddr, 0xff);
|
release_region(wc->ioaddr, 0xff);
|
||||||
pci_free_consistent(pdev, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma);
|
pci_free_consistent(pdev, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma);
|
||||||
pci_set_drvdata(pdev, NULL);
|
pci_set_drvdata(pdev, NULL);
|
||||||
dahdi_unregister(&wc->span);
|
dahdi_unregister_device(wc->ddev);
|
||||||
|
kfree(wc->ddev->location);
|
||||||
|
dahdi_free_device(wc->ddev);
|
||||||
kfree(wc);
|
kfree(wc);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
@ -2708,10 +2728,14 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
|
|||||||
|
|
||||||
static void wctdm_release(struct wctdm *wc)
|
static void wctdm_release(struct wctdm *wc)
|
||||||
{
|
{
|
||||||
dahdi_unregister(&wc->span);
|
dahdi_unregister_device(wc->ddev);
|
||||||
if (wc->freeregion)
|
if (wc->freeregion)
|
||||||
release_region(wc->ioaddr, 0xff);
|
release_region(wc->ioaddr, 0xff);
|
||||||
|
|
||||||
|
kfree(wc->ddev->location);
|
||||||
|
dahdi_free_device(wc->ddev);
|
||||||
kfree(wc);
|
kfree(wc);
|
||||||
|
|
||||||
printk(KERN_INFO "Freed a Wildcard\n");
|
printk(KERN_INFO "Freed a Wildcard\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4366,6 +4366,32 @@ wctdm_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
|
|||||||
return wctdm_wait_for_ready(wc);
|
return wctdm_wait_for_ready(wc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wctdm24xxp_assigned - Called when span is assigned.
|
||||||
|
* @span: The span that is now assigned.
|
||||||
|
*
|
||||||
|
* This function is called by the core of DAHDI after the span number and
|
||||||
|
* channel numbers have been assigned.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void wctdm24xxp_assigned(struct dahdi_span *span)
|
||||||
|
{
|
||||||
|
struct dahdi_span *s;
|
||||||
|
struct dahdi_device *ddev = span->parent;
|
||||||
|
struct wctdm *wc = NULL;
|
||||||
|
|
||||||
|
list_for_each_entry(s, &ddev->spans, device_node) {
|
||||||
|
wc = (container_of(s, struct wctdm_span, span))->wc;
|
||||||
|
if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wc) {
|
||||||
|
WARN_ON(0 == wc->not_ready);
|
||||||
|
--wc->not_ready;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const struct dahdi_span_ops wctdm24xxp_analog_span_ops = {
|
static const struct dahdi_span_ops wctdm24xxp_analog_span_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.hooksig = wctdm_hooksig,
|
.hooksig = wctdm_hooksig,
|
||||||
@ -4375,6 +4401,7 @@ static const struct dahdi_span_ops wctdm24xxp_analog_span_ops = {
|
|||||||
.watchdog = wctdm_watchdog,
|
.watchdog = wctdm_watchdog,
|
||||||
.chanconfig = wctdm_chanconfig,
|
.chanconfig = wctdm_chanconfig,
|
||||||
.dacs = wctdm_dacs,
|
.dacs = wctdm_dacs,
|
||||||
|
.assigned = wctdm24xxp_assigned,
|
||||||
#ifdef VPM_SUPPORT
|
#ifdef VPM_SUPPORT
|
||||||
.enable_hw_preechocan = wctdm_enable_hw_preechocan,
|
.enable_hw_preechocan = wctdm_enable_hw_preechocan,
|
||||||
.disable_hw_preechocan = wctdm_disable_hw_preechocan,
|
.disable_hw_preechocan = wctdm_disable_hw_preechocan,
|
||||||
@ -4393,6 +4420,7 @@ static const struct dahdi_span_ops wctdm24xxp_digital_span_ops = {
|
|||||||
.spanconfig = b400m_spanconfig,
|
.spanconfig = b400m_spanconfig,
|
||||||
.chanconfig = b400m_chanconfig,
|
.chanconfig = b400m_chanconfig,
|
||||||
.dacs = wctdm_dacs,
|
.dacs = wctdm_dacs,
|
||||||
|
.assigned = wctdm24xxp_assigned,
|
||||||
#ifdef VPM_SUPPORT
|
#ifdef VPM_SUPPORT
|
||||||
.enable_hw_preechocan = wctdm_enable_hw_preechocan,
|
.enable_hw_preechocan = wctdm_enable_hw_preechocan,
|
||||||
.disable_hw_preechocan = wctdm_disable_hw_preechocan,
|
.disable_hw_preechocan = wctdm_disable_hw_preechocan,
|
||||||
@ -4473,11 +4501,6 @@ wctdm_init_span(struct wctdm *wc, int spanno, int chanoffset, int chancount,
|
|||||||
sprintf(s->span.name, "WCTDM/%d", card_position);
|
sprintf(s->span.name, "WCTDM/%d", card_position);
|
||||||
|
|
||||||
snprintf(s->span.desc, sizeof(s->span.desc) - 1, "%s", wc->desc->name);
|
snprintf(s->span.desc, sizeof(s->span.desc) - 1, "%s", wc->desc->name);
|
||||||
snprintf(s->span.location, sizeof(s->span.location) - 1,
|
|
||||||
"PCI%s Bus %02d Slot %02d",
|
|
||||||
(wc->desc->flags & FLAG_EXPRESS) ? " Express" : "",
|
|
||||||
pdev->bus->number, PCI_SLOT(pdev->devfn) + 1);
|
|
||||||
s->span.manufacturer = "Digium";
|
|
||||||
|
|
||||||
if (wc->companding == DAHDI_LAW_DEFAULT) {
|
if (wc->companding == DAHDI_LAW_DEFAULT) {
|
||||||
if (wc->digi_mods || digital_span)
|
if (wc->digi_mods || digital_span)
|
||||||
@ -4966,9 +4989,10 @@ static void wctdm_back_out_gracefully(struct wctdm *wc)
|
|||||||
kfree(frame);
|
kfree(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
kfree(wc->board_name);
|
kfree(wc->board_name);
|
||||||
|
kfree(wc->ddev->devicetype);
|
||||||
|
kfree(wc->ddev->location);
|
||||||
|
dahdi_free_device(wc->ddev);
|
||||||
kfree(wc);
|
kfree(wc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5564,27 +5588,6 @@ static void wctdm_allocate_irq_commands(struct wctdm *wc, unsigned int count)
|
|||||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_span_devicetype_string(struct wctdm *wc)
|
|
||||||
{
|
|
||||||
unsigned int x;
|
|
||||||
|
|
||||||
for (x = 0; x < ARRAY_SIZE(wc->spans); x++) {
|
|
||||||
struct dahdi_span *const s = &wc->spans[x]->span;
|
|
||||||
if (!s)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
strlcpy(s->devicetype, wc->desc->name, sizeof(s->devicetype));
|
|
||||||
|
|
||||||
if (wc->vpmadt032) {
|
|
||||||
strlcat(s->devicetype, " (VPMADT032)",
|
|
||||||
sizeof(s->devicetype));
|
|
||||||
} else if (wc->vpmoct) {
|
|
||||||
strlcat(s->devicetype, " (VPMOCT032)",
|
|
||||||
sizeof(s->devicetype));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_ASYNC_INIT
|
#ifdef USE_ASYNC_INIT
|
||||||
struct async_data {
|
struct async_data {
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
@ -5852,27 +5855,56 @@ __wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||||||
|
|
||||||
wc->avchannels = curchan;
|
wc->avchannels = curchan;
|
||||||
|
|
||||||
set_span_devicetype_string(wc);
|
|
||||||
|
|
||||||
#ifdef USE_ASYNC_INIT
|
#ifdef USE_ASYNC_INIT
|
||||||
async_synchronize_cookie(cookie);
|
async_synchronize_cookie(cookie);
|
||||||
#endif
|
#endif
|
||||||
|
wc->ddev = dahdi_create_device();
|
||||||
|
wc->ddev->manufacturer = "Digium";
|
||||||
|
wc->ddev->location = kasprintf(GFP_KERNEL, "PCI%s Bus %02d Slot %02d",
|
||||||
|
(wc->desc->flags & FLAG_EXPRESS) ?
|
||||||
|
" Express" : "",
|
||||||
|
pdev->bus->number,
|
||||||
|
PCI_SLOT(pdev->devfn) + 1);
|
||||||
|
if (!wc->ddev->location) {
|
||||||
|
wctdm_back_out_gracefully(wc);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wc->vpmadt032) {
|
||||||
|
wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s (VPMADT032)",
|
||||||
|
wc->desc->name);
|
||||||
|
} else if (wc->vpmoct) {
|
||||||
|
wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s (VPMOCT032)",
|
||||||
|
wc->desc->name);
|
||||||
|
} else {
|
||||||
|
wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s",
|
||||||
|
wc->desc->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wc->ddev->devicetype) {
|
||||||
|
wctdm_back_out_gracefully(wc);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
/* We should be ready for DAHDI to come in now. */
|
/* We should be ready for DAHDI to come in now. */
|
||||||
for (i = 0; i < MAX_SPANS; ++i) {
|
for (i = 0; i < MAX_SPANS; ++i) {
|
||||||
|
struct dahdi_span *span;
|
||||||
|
|
||||||
if (!wc->spans[i])
|
if (!wc->spans[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (dahdi_register(&wc->spans[i]->span, 0)) {
|
span = &wc->spans[i]->span;
|
||||||
dev_notice(&wc->vb.pdev->dev, "Unable to register span %d with DAHDI\n", i);
|
|
||||||
while (i)
|
list_add_tail(&span->device_node, &wc->ddev->spans);
|
||||||
dahdi_unregister(&wc->spans[i--]->span);
|
|
||||||
wctdm_back_out_gracefully(wc);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wctdm_allocate_irq_commands(wc, anamods * latency * 4);
|
wctdm_allocate_irq_commands(wc, anamods * latency * 4);
|
||||||
wc->not_ready--;
|
|
||||||
|
if (dahdi_register_device(wc->ddev, &wc->vb.pdev->dev)) {
|
||||||
|
dev_notice(&wc->vb.pdev->dev, "Unable to register device with DAHDI\n");
|
||||||
|
wctdm_back_out_gracefully(wc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
dev_info(&wc->vb.pdev->dev,
|
dev_info(&wc->vb.pdev->dev,
|
||||||
"Found a %s: %s (%d BRI spans, %d analog %s)\n",
|
"Found a %s: %s (%d BRI spans, %d analog %s)\n",
|
||||||
@ -5924,12 +5956,8 @@ static void wctdm_release(struct wctdm *wc)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (is_initialized(wc)) {
|
if (is_initialized(wc))
|
||||||
for (i = 0; i < MAX_SPANS; i++) {
|
dahdi_unregister_device(wc->ddev);
|
||||||
if (wc->spans[i])
|
|
||||||
dahdi_unregister(&wc->spans[i]->span);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
down(&ifacelock);
|
down(&ifacelock);
|
||||||
for (i = 0; i < WC_MAX_IFACES; i++)
|
for (i = 0; i < WC_MAX_IFACES; i++)
|
||||||
|
@ -297,6 +297,7 @@ struct wctdm {
|
|||||||
int not_ready; /* 0 when the entire card is ready to go */
|
int not_ready; /* 0 when the entire card is ready to go */
|
||||||
unsigned long checkflag; /* Internal state flags and task bits */
|
unsigned long checkflag; /* Internal state flags and task bits */
|
||||||
int companding;
|
int companding;
|
||||||
|
struct dahdi_device *ddev;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline bool is_initialized(struct wctdm *wc)
|
static inline bool is_initialized(struct wctdm *wc)
|
||||||
|
@ -174,6 +174,7 @@ struct t1 {
|
|||||||
unsigned char ec_chunk1[32][DAHDI_CHUNKSIZE];
|
unsigned char ec_chunk1[32][DAHDI_CHUNKSIZE];
|
||||||
unsigned char ec_chunk2[32][DAHDI_CHUNKSIZE];
|
unsigned char ec_chunk2[32][DAHDI_CHUNKSIZE];
|
||||||
unsigned char tempo[33];
|
unsigned char tempo[33];
|
||||||
|
struct dahdi_device *ddev;
|
||||||
struct dahdi_span span; /* Span */
|
struct dahdi_span span; /* Span */
|
||||||
struct dahdi_chan *chans[32]; /* Channels */
|
struct dahdi_chan *chans[32]; /* Channels */
|
||||||
};
|
};
|
||||||
@ -340,10 +341,12 @@ static void t1xxp_release(struct t1 *wc)
|
|||||||
{
|
{
|
||||||
unsigned int x;
|
unsigned int x;
|
||||||
|
|
||||||
dahdi_unregister(&wc->span);
|
dahdi_unregister_device(wc->ddev);
|
||||||
for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) {
|
for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) {
|
||||||
kfree(wc->chans[x]);
|
kfree(wc->chans[x]);
|
||||||
}
|
}
|
||||||
|
kfree(wc->ddev->location);
|
||||||
|
dahdi_free_device(wc->ddev);
|
||||||
kfree(wc);
|
kfree(wc);
|
||||||
printk(KERN_INFO "Freed a Wildcard\n");
|
printk(KERN_INFO "Freed a Wildcard\n");
|
||||||
}
|
}
|
||||||
@ -976,14 +979,21 @@ static int t1xxp_software_init(struct t1 *wc)
|
|||||||
}
|
}
|
||||||
if (x >= WC_MAX_CARDS)
|
if (x >= WC_MAX_CARDS)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
wc->ddev = dahdi_create_device();
|
||||||
|
|
||||||
t4_serial_setup(wc);
|
t4_serial_setup(wc);
|
||||||
wc->num = x;
|
wc->num = x;
|
||||||
sprintf(wc->span.name, "WCT1/%d", wc->num);
|
sprintf(wc->span.name, "WCT1/%d", wc->num);
|
||||||
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num);
|
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num);
|
||||||
wc->span.manufacturer = "Digium";
|
wc->ddev->manufacturer = "Digium";
|
||||||
strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
|
wc->ddev->devicetype = wc->variety;
|
||||||
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
|
wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
|
||||||
"PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
|
wc->dev->bus->number,
|
||||||
|
PCI_SLOT(wc->dev->devfn) + 1);
|
||||||
|
if (!wc->ddev->location)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
wc->span.irq = wc->dev->irq;
|
wc->span.irq = wc->dev->irq;
|
||||||
if (wc->spantype == TYPE_E1) {
|
if (wc->spantype == TYPE_E1) {
|
||||||
if (unchannelized)
|
if (unchannelized)
|
||||||
@ -1011,7 +1021,8 @@ static int t1xxp_software_init(struct t1 *wc)
|
|||||||
wc->chans[x]->chanpos = x + 1;
|
wc->chans[x]->chanpos = x + 1;
|
||||||
}
|
}
|
||||||
wc->span.ops = &t1xxp_span_ops;
|
wc->span.ops = &t1xxp_span_ops;
|
||||||
if (dahdi_register(&wc->span, 0)) {
|
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
|
||||||
|
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
|
||||||
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -755,7 +755,7 @@ static void __t1xxp_set_clear(struct t1 *wc)
|
|||||||
/* Calculate all states on all 24 channels using the channel
|
/* Calculate all states on all 24 channels using the channel
|
||||||
flags, then write all 3 clear channel registers at once */
|
flags, then write all 3 clear channel registers at once */
|
||||||
|
|
||||||
for (i = 0; i < 24; i++) {
|
for (i = 0; i < wc->span.channels; i++) {
|
||||||
offset = i/8;
|
offset = i/8;
|
||||||
if (wc->span.chans[i]->flags & DAHDI_FLAG_CLEAR)
|
if (wc->span.chans[i]->flags & DAHDI_FLAG_CLEAR)
|
||||||
reg[offset] |= 1 << (7 - (i % 8));
|
reg[offset] |= 1 << (7 - (i % 8));
|
||||||
@ -783,7 +783,7 @@ static void free_wc(struct t1 *wc)
|
|||||||
struct command *cmd;
|
struct command *cmd;
|
||||||
LIST_HEAD(list);
|
LIST_HEAD(list);
|
||||||
|
|
||||||
for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) {
|
for (x = 0; x < ARRAY_SIZE(wc->chans); x++) {
|
||||||
kfree(wc->chans[x]);
|
kfree(wc->chans[x]);
|
||||||
kfree(wc->ec[x]);
|
kfree(wc->ec[x]);
|
||||||
}
|
}
|
||||||
@ -808,14 +808,14 @@ static void free_wc(struct t1 *wc)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
kfree(wc->ddev->location);
|
||||||
|
kfree(wc->ddev->devicetype);
|
||||||
|
dahdi_free_device(wc->ddev);
|
||||||
kfree(wc);
|
kfree(wc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void t4_serial_setup(struct t1 *wc)
|
static void t4_serial_setup(struct t1 *wc)
|
||||||
{
|
{
|
||||||
t1_info(wc, "Setting up global serial parameters for %s\n",
|
|
||||||
((wc->spantype == TYPE_E1) ? "E1" : "T1"));
|
|
||||||
|
|
||||||
t1_setreg(wc, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */
|
t1_setreg(wc, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */
|
||||||
t1_setreg(wc, 0x08, 0x05); /* IPC: Interrupt push/pull active low */
|
t1_setreg(wc, 0x08, 0x05); /* IPC: Interrupt push/pull active low */
|
||||||
|
|
||||||
@ -1009,12 +1009,12 @@ static void t1_configure_e1(struct t1 *wc, int lineconfig)
|
|||||||
t1_info(wc, "Span configured for %s/%s%s\n", framing, line, crc4);
|
t1_info(wc, "Span configured for %s/%s%s\n", framing, line, crc4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void t1xxp_framer_start(struct t1 *wc, struct dahdi_span *span)
|
static void t1xxp_framer_start(struct t1 *wc)
|
||||||
{
|
{
|
||||||
if (wc->spantype == TYPE_E1) { /* if this is an E1 card */
|
if (dahdi_is_e1_span(&wc->span)) {
|
||||||
t1_configure_e1(wc, span->lineconfig);
|
t1_configure_e1(wc, wc->span.lineconfig);
|
||||||
} else { /* is a T1 card */
|
} else { /* is a T1 card */
|
||||||
t1_configure_t1(wc, span->lineconfig, span->txlevel);
|
t1_configure_t1(wc, wc->span.lineconfig, wc->span.txlevel);
|
||||||
__t1xxp_set_clear(wc);
|
__t1xxp_set_clear(wc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1023,18 +1023,28 @@ static void t1xxp_framer_start(struct t1 *wc, struct dahdi_span *span)
|
|||||||
|
|
||||||
static void set_span_devicetype(struct t1 *wc)
|
static void set_span_devicetype(struct t1 *wc)
|
||||||
{
|
{
|
||||||
strncpy(wc->span.devicetype, wc->variety,
|
const char *olddevicetype;
|
||||||
sizeof(wc->span.devicetype) - 1);
|
olddevicetype = wc->ddev->devicetype;
|
||||||
|
|
||||||
#if defined(VPM_SUPPORT)
|
#if defined(VPM_SUPPORT)
|
||||||
if (wc->vpmadt032) {
|
if (wc->vpmadt032) {
|
||||||
strncat(wc->span.devicetype, " (VPMADT032)",
|
wc->ddev->devicetype = kasprintf(GFP_KERNEL,
|
||||||
sizeof(wc->span.devicetype) - 1);
|
"%s (VPMADT032)", wc->variety);
|
||||||
} else if (wc->vpmoct) {
|
} else if (wc->vpmoct) {
|
||||||
strncat(wc->span.devicetype, " (VPMOCT032)",
|
wc->ddev->devicetype = kasprintf(GFP_KERNEL,
|
||||||
sizeof(wc->span.devicetype) - 1);
|
"%s (VPMOCT032)", wc->variety);
|
||||||
|
} else {
|
||||||
|
wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s", wc->variety);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s", wc->variety);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* On the off chance that we were able to allocate it previously. */
|
||||||
|
if (!wc->ddev->devicetype)
|
||||||
|
wc->ddev->devicetype = olddevicetype;
|
||||||
|
else
|
||||||
|
kfree(olddevicetype);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int t1xxp_startup(struct file *file, struct dahdi_span *span)
|
static int t1xxp_startup(struct file *file, struct dahdi_span *span)
|
||||||
@ -1055,7 +1065,7 @@ static int t1xxp_startup(struct file *file, struct dahdi_span *span)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Reset framer with proper parameters and start */
|
/* Reset framer with proper parameters and start */
|
||||||
t1xxp_framer_start(wc, span);
|
t1xxp_framer_start(wc);
|
||||||
debug_printk(wc, 1, "Calling startup (flags is %lu)\n", span->flags);
|
debug_printk(wc, 1, "Calling startup (flags is %lu)\n", span->flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1095,7 +1105,7 @@ static int t1xxp_chanconfig(struct file *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (test_bit(DAHDI_FLAGBIT_RUNNING, &chan->span->flags) &&
|
if (test_bit(DAHDI_FLAGBIT_RUNNING, &chan->span->flags) &&
|
||||||
(wc->spantype != TYPE_E1)) {
|
dahdi_is_t1_span(&wc->span)) {
|
||||||
__t1xxp_set_clear(wc);
|
__t1xxp_set_clear(wc);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1110,7 +1120,7 @@ static int t1xxp_rbsbits(struct dahdi_chan *chan, int bits)
|
|||||||
|
|
||||||
debug_printk(wc, 2, "Setting bits to %d on channel %s\n",
|
debug_printk(wc, 2, "Setting bits to %d on channel %s\n",
|
||||||
bits, chan->name);
|
bits, chan->name);
|
||||||
if (wc->spantype == TYPE_E1) { /* do it E1 way */
|
if (dahdi_is_e1_span(&wc->span)) { /* do it E1 way */
|
||||||
if (chan->chanpos == 16)
|
if (chan->chanpos == 16)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1163,7 +1173,7 @@ static inline void t1_check_sigbits(struct t1 *wc)
|
|||||||
|
|
||||||
if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags)))
|
if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags)))
|
||||||
return;
|
return;
|
||||||
if (wc->spantype == TYPE_E1) {
|
if (dahdi_is_e1_span(&wc->span)) {
|
||||||
for (i = 0; i < 15; i++) {
|
for (i = 0; i < 15; i++) {
|
||||||
a = t1_getreg(wc, 0x71 + i);
|
a = t1_getreg(wc, 0x71 + i);
|
||||||
if (a > -1) {
|
if (a > -1) {
|
||||||
@ -1258,7 +1268,7 @@ static void t1xxp_maint_work(struct work_struct *work)
|
|||||||
int reg = 0;
|
int reg = 0;
|
||||||
int cmd = w->cmd;
|
int cmd = w->cmd;
|
||||||
|
|
||||||
if (wc->spantype == TYPE_E1) {
|
if (dahdi_is_e1_span(&wc->span)) {
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case DAHDI_MAINT_NONE:
|
case DAHDI_MAINT_NONE:
|
||||||
t1_info(wc, "Clearing all maint modes\n");
|
t1_info(wc, "Clearing all maint modes\n");
|
||||||
@ -1330,7 +1340,7 @@ static int t1xxp_maint(struct dahdi_span *span, int cmd)
|
|||||||
struct maint_work_struct *work;
|
struct maint_work_struct *work;
|
||||||
struct t1 *wc = container_of(span, struct t1, span);
|
struct t1 *wc = container_of(span, struct t1, span);
|
||||||
|
|
||||||
if (wc->spantype == TYPE_E1) {
|
if (dahdi_is_e1_span(&wc->span)) {
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case DAHDI_MAINT_NONE:
|
case DAHDI_MAINT_NONE:
|
||||||
case DAHDI_MAINT_LOCALLOOP:
|
case DAHDI_MAINT_LOCALLOOP:
|
||||||
@ -1625,7 +1635,7 @@ static void check_and_load_vpm(struct t1 *wc)
|
|||||||
options.vpmnlptype = vpmnlptype;
|
options.vpmnlptype = vpmnlptype;
|
||||||
options.vpmnlpthresh = vpmnlpthresh;
|
options.vpmnlpthresh = vpmnlpthresh;
|
||||||
options.vpmnlpmaxsupp = vpmnlpmaxsupp;
|
options.vpmnlpmaxsupp = vpmnlpmaxsupp;
|
||||||
options.channels = (TYPE_T1 == wc->spantype) ? 24 : 32;
|
options.channels = dahdi_is_t1_span(&wc->span) ? 24 : 32;
|
||||||
|
|
||||||
/* We do not want to check that the VPM is alive until after we're
|
/* We do not want to check that the VPM is alive until after we're
|
||||||
* done setting it up here, an hour should cover it... */
|
* done setting it up here, an hour should cover it... */
|
||||||
@ -1685,7 +1695,7 @@ static void t1_chan_set_sigcap(struct dahdi_span *span, int x)
|
|||||||
struct dahdi_chan *chan = wc->chans[x];
|
struct dahdi_chan *chan = wc->chans[x];
|
||||||
chan->sigcap = DAHDI_SIG_CLEAR;
|
chan->sigcap = DAHDI_SIG_CLEAR;
|
||||||
/* E&M variant supported depends on span type */
|
/* E&M variant supported depends on span type */
|
||||||
if (wc->spantype == TYPE_E1) {
|
if (dahdi_is_e1_span(&wc->span)) {
|
||||||
/* E1 sigcap setup */
|
/* E1 sigcap setup */
|
||||||
if (span->lineconfig & DAHDI_CONFIG_CCS) {
|
if (span->lineconfig & DAHDI_CONFIG_CCS) {
|
||||||
/* CCS setup */
|
/* CCS setup */
|
||||||
@ -1784,9 +1794,19 @@ static const struct dahdi_span_ops t1_span_ops = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static int t1_software_init(struct t1 *wc)
|
/**
|
||||||
|
* t1_software_init - Initialize the board for the given type.
|
||||||
|
* @wc: The board to initialize.
|
||||||
|
* @type: The type of board we are, T1 / E1
|
||||||
|
*
|
||||||
|
* This function is called at startup and when the type of the span is changed
|
||||||
|
* via the dahdi_device before the span is assigned a number.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int t1_software_init(struct t1 *wc, enum linemode type)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
|
int res;
|
||||||
int num;
|
int num;
|
||||||
struct pci_dev *pdev = wc->vb.pdev;
|
struct pci_dev *pdev = wc->vb.pdev;
|
||||||
|
|
||||||
@ -1801,21 +1821,23 @@ static int t1_software_init(struct t1 *wc)
|
|||||||
if (x == ARRAY_SIZE(ifaces))
|
if (x == ARRAY_SIZE(ifaces))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
t4_serial_setup(wc);
|
|
||||||
|
|
||||||
num = x;
|
num = x;
|
||||||
sprintf(wc->span.name, "WCT1/%d", num);
|
sprintf(wc->span.name, "WCT1/%d", num);
|
||||||
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, num);
|
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, num);
|
||||||
wc->span.manufacturer = "Digium";
|
wc->ddev->manufacturer = "Digium";
|
||||||
set_span_devicetype(wc);
|
set_span_devicetype(wc);
|
||||||
|
|
||||||
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
|
wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
|
||||||
"PCI Bus %02d Slot %02d", pdev->bus->number,
|
pdev->bus->number,
|
||||||
PCI_SLOT(pdev->devfn) + 1);
|
PCI_SLOT(pdev->devfn) + 1);
|
||||||
|
|
||||||
|
if (!wc->ddev->location)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
wc->span.irq = pdev->irq;
|
wc->span.irq = pdev->irq;
|
||||||
|
|
||||||
if (wc->spantype == TYPE_E1) {
|
if (type == E1) {
|
||||||
wc->span.channels = 31;
|
wc->span.channels = 31;
|
||||||
wc->span.spantype = "E1";
|
wc->span.spantype = "E1";
|
||||||
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_HDB3 |
|
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_HDB3 |
|
||||||
@ -1828,6 +1850,11 @@ static int t1_software_init(struct t1 *wc)
|
|||||||
DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
|
DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
|
||||||
wc->span.deflaw = DAHDI_LAW_MULAW;
|
wc->span.deflaw = DAHDI_LAW_MULAW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t1_info(wc, "Setting up global serial parameters for %s\n",
|
||||||
|
(dahdi_is_e1_span(&wc->span) ? "E1" : "T1"));
|
||||||
|
|
||||||
|
t4_serial_setup(wc);
|
||||||
wc->span.chans = wc->chans;
|
wc->span.chans = wc->chans;
|
||||||
set_bit(DAHDI_FLAGBIT_RBS, &wc->span.flags);
|
set_bit(DAHDI_FLAGBIT_RBS, &wc->span.flags);
|
||||||
for (x = 0; x < wc->span.channels; x++) {
|
for (x = 0; x < wc->span.channels; x++) {
|
||||||
@ -1840,9 +1867,11 @@ static int t1_software_init(struct t1 *wc)
|
|||||||
check_and_load_vpm(wc);
|
check_and_load_vpm(wc);
|
||||||
|
|
||||||
wc->span.ops = &t1_span_ops;
|
wc->span.ops = &t1_span_ops;
|
||||||
if (dahdi_register(&wc->span, 0)) {
|
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
|
||||||
t1_info(wc, "Unable to register span with DAHDI\n");
|
res = dahdi_register_device(wc->ddev, &wc->vb.pdev->dev);
|
||||||
return -1;
|
if (res) {
|
||||||
|
t1_info(wc, "Unable to register with DAHDI\n");
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1864,7 +1893,7 @@ static inline unsigned char t1_vpm_out(struct t1 *wc, int unit, const unsigned i
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int t1_hardware_post_init(struct t1 *wc)
|
static int t1_hardware_post_init(struct t1 *wc, enum linemode *type)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
int reg;
|
int reg;
|
||||||
@ -1872,22 +1901,22 @@ static int t1_hardware_post_init(struct t1 *wc)
|
|||||||
|
|
||||||
/* T1 or E1 */
|
/* T1 or E1 */
|
||||||
if (-1 != t1e1override) {
|
if (-1 != t1e1override) {
|
||||||
pr_info("t1e1override is deprecated. Please use 'spantype'.\n");
|
pr_info("t1e1override is deprecated. Please use 'default_linemode'.\n");
|
||||||
wc->spantype = (t1e1override) ? TYPE_E1 : TYPE_T1;
|
*type = (t1e1override) ? E1 : T1;
|
||||||
} else {
|
} else {
|
||||||
if (!strcasecmp(default_linemode, "e1")) {
|
if (!strcasecmp(default_linemode, "e1")) {
|
||||||
wc->spantype = TYPE_E1;
|
*type = E1;
|
||||||
} else if (!strcasecmp(default_linemode, "t1")) {
|
} else if (!strcasecmp(default_linemode, "t1")) {
|
||||||
wc->spantype = TYPE_T1;
|
*type = T1;
|
||||||
} else {
|
} else {
|
||||||
u8 pins;
|
u8 pins;
|
||||||
res = t1_getpins(wc, &pins);
|
res = t1_getpins(wc, &pins);
|
||||||
if (res)
|
if (res)
|
||||||
return res;
|
return res;
|
||||||
wc->spantype = (pins & 0x01) ? TYPE_T1 : TYPE_E1;
|
*type = (pins & 0x01) ? T1 : E1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug_printk(wc, 1, "linemode: %s\n", 1 == wc->spantype ? "T1" : "E1");
|
debug_printk(wc, 1, "linemode: %s\n", (*type == T1) ? "T1" : "E1");
|
||||||
|
|
||||||
/* what version of the FALC are we using? */
|
/* what version of the FALC are we using? */
|
||||||
reg = t1_setreg(wc, 0x4a, 0xaa);
|
reg = t1_setreg(wc, 0x4a, 0xaa);
|
||||||
@ -1938,7 +1967,7 @@ static inline void t1_check_alarms(struct t1 *wc)
|
|||||||
/* And consider only carrier alarms */
|
/* And consider only carrier alarms */
|
||||||
wc->span.alarms &= (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_ALARM_NOTOPEN);
|
wc->span.alarms &= (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_ALARM_NOTOPEN);
|
||||||
|
|
||||||
if (wc->spantype == TYPE_E1) {
|
if (dahdi_is_e1_span(&wc->span)) {
|
||||||
if (c & 0x04) {
|
if (c & 0x04) {
|
||||||
/* No multiframe found, force RAI high after 400ms only if
|
/* No multiframe found, force RAI high after 400ms only if
|
||||||
we haven't found a multiframe since last loss
|
we haven't found a multiframe since last loss
|
||||||
@ -2555,6 +2584,7 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
|
|||||||
unsigned int x;
|
unsigned int x;
|
||||||
int res;
|
int res;
|
||||||
unsigned int index = -1;
|
unsigned int index = -1;
|
||||||
|
enum linemode type;
|
||||||
|
|
||||||
for (x = 0; x < ARRAY_SIZE(ifaces); x++) {
|
for (x = 0; x < ARRAY_SIZE(ifaces); x++) {
|
||||||
if (!ifaces[x]) {
|
if (!ifaces[x]) {
|
||||||
@ -2582,6 +2612,7 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
|
|||||||
ifaces[index] = wc;
|
ifaces[index] = wc;
|
||||||
|
|
||||||
wc->ledstate = -1;
|
wc->ledstate = -1;
|
||||||
|
wc->ddev = dahdi_create_device();
|
||||||
spin_lock_init(&wc->reglock);
|
spin_lock_init(&wc->reglock);
|
||||||
INIT_LIST_HEAD(&wc->active_cmds);
|
INIT_LIST_HEAD(&wc->active_cmds);
|
||||||
INIT_LIST_HEAD(&wc->pending_cmds);
|
INIT_LIST_HEAD(&wc->pending_cmds);
|
||||||
@ -2656,14 +2687,14 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = t1_hardware_post_init(wc);
|
res = t1_hardware_post_init(wc, &type);
|
||||||
if (res) {
|
if (res) {
|
||||||
voicebus_release(&wc->vb);
|
voicebus_release(&wc->vb);
|
||||||
free_wc(wc);
|
free_wc(wc);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) {
|
for (x = 0; x < ((E1 == type) ? 31 : 24); x++) {
|
||||||
wc->chans[x] = kzalloc(sizeof(*wc->chans[x]), GFP_KERNEL);
|
wc->chans[x] = kzalloc(sizeof(*wc->chans[x]), GFP_KERNEL);
|
||||||
if (!wc->chans[x]) {
|
if (!wc->chans[x]) {
|
||||||
free_wc(wc);
|
free_wc(wc);
|
||||||
@ -2679,7 +2710,7 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res = t1_software_init(wc);
|
res = t1_software_init(wc, type);
|
||||||
if (res) {
|
if (res) {
|
||||||
voicebus_release(&wc->vb);
|
voicebus_release(&wc->vb);
|
||||||
free_wc(wc);
|
free_wc(wc);
|
||||||
@ -2710,7 +2741,7 @@ static void __devexit te12xp_remove_one(struct pci_dev *pdev)
|
|||||||
if (!wc)
|
if (!wc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dahdi_unregister(&wc->span);
|
dahdi_unregister_device(wc->ddev);
|
||||||
|
|
||||||
remove_sysfs_files(wc);
|
remove_sysfs_files(wc);
|
||||||
|
|
||||||
|
@ -74,8 +74,10 @@
|
|||||||
#define CMD_BYTE(slot, a, is_vpm) (slot*6)+(a*2)+is_vpm /* only even slots */
|
#define CMD_BYTE(slot, a, is_vpm) (slot*6)+(a*2)+is_vpm /* only even slots */
|
||||||
//TODO: make a separate macro
|
//TODO: make a separate macro
|
||||||
|
|
||||||
#define TYPE_T1 1
|
enum linemode {
|
||||||
#define TYPE_E1 2
|
T1 = 1,
|
||||||
|
E1,
|
||||||
|
};
|
||||||
|
|
||||||
struct command {
|
struct command {
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
@ -94,7 +96,6 @@ struct t1 {
|
|||||||
unsigned char txident;
|
unsigned char txident;
|
||||||
unsigned char rxident;
|
unsigned char rxident;
|
||||||
unsigned char statreg; /* bit 0 = vpmadt032 int */
|
unsigned char statreg; /* bit 0 = vpmadt032 int */
|
||||||
int spantype;
|
|
||||||
struct {
|
struct {
|
||||||
unsigned int nmf:1;
|
unsigned int nmf:1;
|
||||||
unsigned int sendingyellow:1;
|
unsigned int sendingyellow:1;
|
||||||
@ -116,6 +117,7 @@ struct t1 {
|
|||||||
unsigned long alarmtimer;
|
unsigned long alarmtimer;
|
||||||
unsigned char ledstate;
|
unsigned char ledstate;
|
||||||
unsigned char vpm_check_count;
|
unsigned char vpm_check_count;
|
||||||
|
struct dahdi_device *ddev;
|
||||||
struct dahdi_span span; /* Span */
|
struct dahdi_span span; /* Span */
|
||||||
struct dahdi_chan *chans[32]; /* Channels */
|
struct dahdi_chan *chans[32]; /* Channels */
|
||||||
struct dahdi_echocan_state *ec[32]; /* Echocan state for channels */
|
struct dahdi_echocan_state *ec[32]; /* Echocan state for channels */
|
||||||
|
@ -871,6 +871,86 @@ err:
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int xbus_register_dahdi_device(xbus_t *xbus)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
XBUS_NOTICE(xbus, "Entering %s\n", __func__);
|
||||||
|
xbus->ddev = dahdi_create_device();
|
||||||
|
/*
|
||||||
|
* This actually describe the dahdi_spaninfo version 3
|
||||||
|
* A bunch of unrelated data exported via a modified ioctl()
|
||||||
|
* What a bummer...
|
||||||
|
*/
|
||||||
|
xbus->ddev->manufacturer = "Xorcom Inc."; /* OK, that's obvious */
|
||||||
|
/* span->spantype = "...."; set in card_dahdi_preregistration() */
|
||||||
|
/*
|
||||||
|
* Yes, this basically duplicates information available
|
||||||
|
* from the description field. If some more is needed
|
||||||
|
* why not add it there?
|
||||||
|
* OK, let's add to the kernel more useless info.
|
||||||
|
*/
|
||||||
|
xbus->ddev->devicetype = kasprintf(GFP_KERNEL, "Astribank2");
|
||||||
|
if (!xbus->ddev->devicetype)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* location is the only usefull new data item.
|
||||||
|
* For our devices it was available for ages via:
|
||||||
|
* - The legacy "/proc/xpp/XBUS-??/summary" (CONNECTOR=...)
|
||||||
|
* - The same info in "/proc/xpp/xbuses"
|
||||||
|
* - The modern "/sys/bus/astribanks/devices/xbus-??/connector" attribute
|
||||||
|
* So let's also export it via the newfangled "location" field.
|
||||||
|
*/
|
||||||
|
xbus->ddev->location = xbus->connector;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare the span list
|
||||||
|
*/
|
||||||
|
for (i = 0; i < MAX_XPDS; i++) {
|
||||||
|
xpd_t *xpd = xpd_of(xbus, i);
|
||||||
|
if (xpd && IS_PHONEDEV(xpd)) {
|
||||||
|
XPD_DBG(DEVICES, xpd, "offset=%d\n", offset);
|
||||||
|
xpd_dahdi_preregister(xpd, offset++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dahdi_register_device(xbus->ddev, &xbus->astribank)) {
|
||||||
|
XBUS_ERR(xbus, "Failed to dahdi_register_device()\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
for (i = 0; i < MAX_XPDS; i++) {
|
||||||
|
xpd_t *xpd = xpd_of(xbus, i);
|
||||||
|
if (xpd && IS_PHONEDEV(xpd)) {
|
||||||
|
XPD_DBG(DEVICES, xpd, "\n");
|
||||||
|
xpd_dahdi_postregister(xpd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xbus_unregister_dahdi_device(xbus_t *xbus)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
XBUS_NOTICE(xbus, "%s\n", __func__);
|
||||||
|
for(i = 0; i < MAX_XPDS; i++) {
|
||||||
|
xpd_t *xpd = xpd_of(xbus, i);
|
||||||
|
xpd_dahdi_preunregister(xpd);
|
||||||
|
}
|
||||||
|
dahdi_unregister_device(xbus->ddev);
|
||||||
|
XBUS_NOTICE(xbus, "%s: finished dahdi_unregister_device()\n", __func__);
|
||||||
|
kfree(xbus->ddev->devicetype);
|
||||||
|
xbus->ddev->devicetype = NULL;
|
||||||
|
xbus->ddev->location = NULL;
|
||||||
|
dahdi_free_device(xbus->ddev);
|
||||||
|
xbus->ddev = NULL;
|
||||||
|
for(i = 0; i < MAX_XPDS; i++) {
|
||||||
|
xpd_t *xpd = xpd_of(xbus, i);
|
||||||
|
xpd_dahdi_postunregister(xpd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This must be called from synchronous (non-interrupt) context
|
* This must be called from synchronous (non-interrupt) context
|
||||||
* it returns only when all XPD's on the bus are detected and
|
* it returns only when all XPD's on the bus are detected and
|
||||||
@ -934,6 +1014,7 @@ void xbus_populate(void *data)
|
|||||||
*/
|
*/
|
||||||
xbus_request_sync(xbus, SYNC_MODE_PLL);
|
xbus_request_sync(xbus, SYNC_MODE_PLL);
|
||||||
elect_syncer("xbus_populate(end)"); /* FIXME: try to do it later */
|
elect_syncer("xbus_populate(end)"); /* FIXME: try to do it later */
|
||||||
|
xbus_register_dahdi_device(xbus);
|
||||||
out:
|
out:
|
||||||
XBUS_DBG(DEVICES, xbus, "Leaving\n");
|
XBUS_DBG(DEVICES, xbus, "Leaving\n");
|
||||||
wake_up_interruptible_all(&worker->wait_for_xpd_initialization);
|
wake_up_interruptible_all(&worker->wait_for_xpd_initialization);
|
||||||
@ -1206,12 +1287,12 @@ void xbus_deactivate(xbus_t *xbus)
|
|||||||
xbus_request_sync(xbus, SYNC_MODE_NONE); /* no more ticks */
|
xbus_request_sync(xbus, SYNC_MODE_NONE); /* no more ticks */
|
||||||
elect_syncer("deactivate");
|
elect_syncer("deactivate");
|
||||||
xbus_echocancel(xbus, 0);
|
xbus_echocancel(xbus, 0);
|
||||||
xbus_request_removal(xbus);
|
|
||||||
XBUS_DBG(DEVICES, xbus, "[%s] Waiting for queues\n", xbus->label);
|
XBUS_DBG(DEVICES, xbus, "[%s] Waiting for queues\n", xbus->label);
|
||||||
xbus_command_queue_clean(xbus);
|
xbus_command_queue_clean(xbus);
|
||||||
xbus_command_queue_waitempty(xbus);
|
xbus_command_queue_waitempty(xbus);
|
||||||
xbus_setstate(xbus, XBUS_STATE_DEACTIVATED);
|
xbus_setstate(xbus, XBUS_STATE_DEACTIVATED);
|
||||||
worker_reset(xbus);
|
worker_reset(xbus);
|
||||||
|
xbus_unregister_dahdi_device(xbus);
|
||||||
xbus_release_xpds(xbus); /* taken in xpd_alloc() [kref_init] */
|
xbus_release_xpds(xbus); /* taken in xpd_alloc() [kref_init] */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1788,10 +1869,6 @@ err:
|
|||||||
|
|
||||||
void xbus_core_shutdown(void)
|
void xbus_core_shutdown(void)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = 0; i < MAX_BUSES; i++)
|
|
||||||
BUG_ON(xbus_num(i));
|
|
||||||
xbus_core_cleanup();
|
xbus_core_cleanup();
|
||||||
xpp_driver_exit();
|
xpp_driver_exit();
|
||||||
}
|
}
|
||||||
|
@ -188,6 +188,7 @@ struct xbus {
|
|||||||
char label[LABEL_SIZE];
|
char label[LABEL_SIZE];
|
||||||
byte revision; /* Protocol revision */
|
byte revision; /* Protocol revision */
|
||||||
struct xbus_transport transport;
|
struct xbus_transport transport;
|
||||||
|
struct dahdi_device *ddev;
|
||||||
|
|
||||||
int num;
|
int num;
|
||||||
struct xpd *xpds[MAX_XPDS];
|
struct xpd *xpds[MAX_XPDS];
|
||||||
|
@ -623,29 +623,6 @@ static DEVICE_ATTR_READER(span_show, dev, buf)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
|
|
||||||
{
|
|
||||||
xpd_t *xpd;
|
|
||||||
int dahdi_reg;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
BUG_ON(!dev);
|
|
||||||
xpd = dev_to_xpd(dev);
|
|
||||||
if(!xpd)
|
|
||||||
return -ENODEV;
|
|
||||||
ret = sscanf(buf, "%d", &dahdi_reg);
|
|
||||||
if(ret != 1)
|
|
||||||
return -EINVAL;
|
|
||||||
if(!XBUS_IS(xpd->xbus, READY))
|
|
||||||
return -ENODEV;
|
|
||||||
XPD_DBG(GENERAL, xpd, "%s\n", (dahdi_reg) ? "register" : "unregister");
|
|
||||||
if(dahdi_reg)
|
|
||||||
ret = dahdi_register_xpd(xpd);
|
|
||||||
else
|
|
||||||
ret = dahdi_unregister_xpd(xpd);
|
|
||||||
return (ret < 0) ? ret : count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DEVICE_ATTR_READER(type_show, dev, buf)
|
static DEVICE_ATTR_READER(type_show, dev, buf)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
@ -728,7 +705,7 @@ static int xpd_match(struct device *dev, struct device_driver *driver)
|
|||||||
static struct device_attribute xpd_dev_attrs[] = {
|
static struct device_attribute xpd_dev_attrs[] = {
|
||||||
__ATTR(chipregs, S_IRUGO | S_IWUSR, chipregs_show, chipregs_store),
|
__ATTR(chipregs, S_IRUGO | S_IWUSR, chipregs_show, chipregs_store),
|
||||||
__ATTR(blink, S_IRUGO | S_IWUSR, blink_show, blink_store),
|
__ATTR(blink, S_IRUGO | S_IWUSR, blink_show, blink_store),
|
||||||
__ATTR(span, S_IRUGO | S_IWUSR, span_show, span_store),
|
__ATTR_RO(span),
|
||||||
__ATTR_RO(type),
|
__ATTR_RO(type),
|
||||||
__ATTR_RO(offhook),
|
__ATTR_RO(offhook),
|
||||||
__ATTR_RO(timing_priority),
|
__ATTR_RO(timing_priority),
|
||||||
|
@ -256,8 +256,8 @@ int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
|
|||||||
void xpd_post_init(xpd_t *xpd)
|
void xpd_post_init(xpd_t *xpd)
|
||||||
{
|
{
|
||||||
XPD_DBG(DEVICES, xpd, "\n");
|
XPD_DBG(DEVICES, xpd, "\n");
|
||||||
if(dahdi_autoreg)
|
/* DEBUG if(dahdi_autoreg) */
|
||||||
dahdi_register_xpd(xpd);
|
/* DEBUG dahdi_register_xpd(xpd); */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
@ -568,46 +568,6 @@ err:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Try our best to make asterisk close all channels related to
|
|
||||||
* this Astribank:
|
|
||||||
* - Set span state to DAHDI_ALARM_NOTOPEN in all relevant spans.
|
|
||||||
* - Notify dahdi afterwards about spans (so it can see all changes at once).
|
|
||||||
* - Also send DAHDI_EVENT_REMOVED on all channels.
|
|
||||||
*/
|
|
||||||
void xbus_request_removal(xbus_t *xbus)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = 0; i < MAX_XPDS; i++) {
|
|
||||||
xpd_t *xpd = xpd_of(xbus, i);
|
|
||||||
if(xpd) {
|
|
||||||
XPD_DBG(DEVICES, xpd, "\n");
|
|
||||||
spin_lock_irqsave(&xpd->lock, flags);
|
|
||||||
xpd->card_present = 0;
|
|
||||||
xpd_setstate(xpd, XPD_STATE_NOHW);
|
|
||||||
PHONEDEV(xpd).span.alarms = DAHDI_ALARM_NOTOPEN;
|
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Now notify dahdi */
|
|
||||||
for(i = 0; i < MAX_XPDS; i++) {
|
|
||||||
xpd_t *xpd = xpd_of(xbus, i);
|
|
||||||
if(xpd) {
|
|
||||||
if(SPAN_REGISTERED(xpd)) {
|
|
||||||
int j;
|
|
||||||
|
|
||||||
dahdi_alarm_notify(&PHONEDEV(xpd).span);
|
|
||||||
XPD_DBG(DEVICES, xpd, "Queuing DAHDI_EVENT_REMOVED on all channels to ask user to release them\n");
|
|
||||||
for (j=0; j<PHONEDEV(xpd).span.channels; j++) {
|
|
||||||
dahdi_qevent_lock(XPD_CHAN(xpd, j),DAHDI_EVENT_REMOVED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The xpd isn't open by anyone, we can unregister it and free it
|
* The xpd isn't open by anyone, we can unregister it and free it
|
||||||
*/
|
*/
|
||||||
@ -615,7 +575,6 @@ void xpd_remove(xpd_t *xpd)
|
|||||||
{
|
{
|
||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
XPD_INFO(xpd, "Remove\n");
|
XPD_INFO(xpd, "Remove\n");
|
||||||
dahdi_unregister_xpd(xpd);
|
|
||||||
CALL_XMETHOD(card_remove, xpd);
|
CALL_XMETHOD(card_remove, xpd);
|
||||||
xpd_free(xpd);
|
xpd_free(xpd);
|
||||||
}
|
}
|
||||||
@ -992,48 +951,6 @@ int xpp_echocan_create(struct dahdi_chan *chan,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(xpp_echocan_create);
|
EXPORT_SYMBOL(xpp_echocan_create);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unregister an xpd from dahdi and release related resources
|
|
||||||
* @xpd The xpd to be unregistered
|
|
||||||
* @returns 0 on success, errno otherwise
|
|
||||||
*
|
|
||||||
* Checks that nobody holds an open channel.
|
|
||||||
*
|
|
||||||
* Called by:
|
|
||||||
* - User action through /proc
|
|
||||||
* - During xpd_remove()
|
|
||||||
*/
|
|
||||||
int dahdi_unregister_xpd(xpd_t *xpd)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
BUG_ON(!xpd);
|
|
||||||
spin_lock_irqsave(&xpd->lock, flags);
|
|
||||||
|
|
||||||
if (!IS_PHONEDEV(xpd)) {
|
|
||||||
XPD_ERR(xpd, "Not a telephony device\n");
|
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
|
||||||
return -EBADF;
|
|
||||||
}
|
|
||||||
if(!SPAN_REGISTERED(xpd)) {
|
|
||||||
XPD_NOTICE(xpd, "Already unregistered\n");
|
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
|
||||||
return -EIDRM;
|
|
||||||
}
|
|
||||||
update_xpd_status(xpd, DAHDI_ALARM_NOTOPEN);
|
|
||||||
mdelay(2); // FIXME: This is to give chance for transmit/receiveprep to finish.
|
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
|
||||||
if(xpd->card_present)
|
|
||||||
CALL_PHONE_METHOD(card_dahdi_preregistration, xpd, 0);
|
|
||||||
atomic_dec(&PHONEDEV(xpd).dahdi_registered);
|
|
||||||
atomic_dec(&num_registered_spans);
|
|
||||||
dahdi_unregister(&PHONEDEV(xpd).span);
|
|
||||||
if(xpd->card_present)
|
|
||||||
CALL_PHONE_METHOD(card_dahdi_postregistration, xpd, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct dahdi_span_ops xpp_span_ops = {
|
static const struct dahdi_span_ops xpp_span_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.open = xpp_open,
|
.open = xpp_open,
|
||||||
@ -1055,12 +972,39 @@ static const struct dahdi_span_ops xpp_rbs_span_ops = {
|
|||||||
.echocan_name = xpp_echocan_name,
|
.echocan_name = xpp_echocan_name,
|
||||||
};
|
};
|
||||||
|
|
||||||
int dahdi_register_xpd(xpd_t *xpd)
|
static void xpd_init_span(xpd_t *xpd, unsigned offset, int cn)
|
||||||
{
|
{
|
||||||
struct dahdi_span *span;
|
struct dahdi_span *span;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
XPD_NOTICE(xpd, "Initializing span(offset=%d): %d channels.\n", offset, cn);
|
||||||
|
memset(&PHONEDEV(xpd).span, 0, sizeof(struct dahdi_span));
|
||||||
|
for (i = 0; i < cn; i++)
|
||||||
|
memset(XPD_CHAN(xpd, i), 0, sizeof(struct dahdi_chan));
|
||||||
|
|
||||||
|
span = &PHONEDEV(xpd).span;
|
||||||
|
snprintf(span->name, MAX_SPANNAME, "%s/%s", xpd->xbus->busname, xpd->xpdname);
|
||||||
|
span->deflaw = DAHDI_LAW_MULAW; /* default, may be overriden by card_* drivers */
|
||||||
|
span->channels = cn;
|
||||||
|
span->chans = PHONEDEV(xpd).chans;
|
||||||
|
|
||||||
|
span->flags = DAHDI_FLAG_RBS;
|
||||||
|
span->offset = offset;
|
||||||
|
if (PHONEDEV(xpd).phoneops->card_hooksig)
|
||||||
|
span->ops = &xpp_rbs_span_ops; /* Only with RBS bits */
|
||||||
|
else
|
||||||
|
span->ops = &xpp_span_ops;
|
||||||
|
|
||||||
|
snprintf(PHONEDEV(xpd).span.desc, MAX_SPANDESC, "Xorcom XPD #%02d/%1d%1d: %s",
|
||||||
|
xpd->xbus->num, xpd->addr.unit, xpd->addr.subunit, xpd->type_name);
|
||||||
|
list_add_tail(&span->device_node, &xpd->xbus->ddev->spans);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset)
|
||||||
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
int cn;
|
int cn;
|
||||||
int i;
|
struct phonedev *phonedev;
|
||||||
|
|
||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
|
|
||||||
@ -1070,70 +1014,25 @@ int dahdi_register_xpd(xpd_t *xpd)
|
|||||||
XPD_ERR(xpd, "Not a telephony device\n");
|
XPD_ERR(xpd, "Not a telephony device\n");
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
phonedev = &PHONEDEV(xpd);
|
||||||
|
|
||||||
if (SPAN_REGISTERED(xpd)) {
|
if (SPAN_REGISTERED(xpd)) {
|
||||||
XPD_ERR(xpd, "Already registered\n");
|
XPD_ERR(xpd, "Already registered\n");
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
cn = PHONEDEV(xpd).channels;
|
cn = PHONEDEV(xpd).channels;
|
||||||
XPD_DBG(DEVICES, xpd, "Initializing span: %d channels.\n", cn);
|
xpd_init_span(xpd, offset, cn);
|
||||||
memset(&PHONEDEV(xpd).span, 0, sizeof(struct dahdi_span));
|
|
||||||
for(i = 0; i < cn; i++) {
|
|
||||||
memset(XPD_CHAN(xpd, i), 0, sizeof(struct dahdi_chan));
|
|
||||||
}
|
|
||||||
|
|
||||||
span = &PHONEDEV(xpd).span;
|
|
||||||
snprintf(span->name, MAX_SPANNAME, "%s/%s", xbus->busname, xpd->xpdname);
|
|
||||||
span->deflaw = DAHDI_LAW_MULAW; /* default, may be overriden by card_* drivers */
|
|
||||||
span->channels = cn;
|
|
||||||
span->chans = PHONEDEV(xpd).chans;
|
|
||||||
|
|
||||||
span->flags = DAHDI_FLAG_RBS;
|
|
||||||
if(PHONEDEV(xpd).phoneops->card_hooksig)
|
|
||||||
span->ops = &xpp_rbs_span_ops; /* Only with RBS bits */
|
|
||||||
else
|
|
||||||
span->ops = &xpp_span_ops;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This actually describe the dahdi_spaninfo version 3
|
|
||||||
* A bunch of unrelated data exported via a modified ioctl()
|
|
||||||
* What a bummer...
|
|
||||||
*/
|
|
||||||
span->manufacturer = "Xorcom Inc."; /* OK, that's obvious */
|
|
||||||
/* span->spantype = "...."; set in card_dahdi_preregistration() */
|
|
||||||
/*
|
|
||||||
* Yes, this basically duplicates information available
|
|
||||||
* from the description field. If some more is needed
|
|
||||||
* why not add it there?
|
|
||||||
* OK, let's add to the kernel more useless info.
|
|
||||||
*/
|
|
||||||
snprintf(span->devicetype, sizeof(span->devicetype) - 1,
|
|
||||||
"Astribank: Unit %x Subunit %x: %s",
|
|
||||||
XBUS_UNIT(xpd->xbus_idx), XBUS_SUBUNIT(xpd->xbus_idx),
|
|
||||||
xpd->type_name);
|
|
||||||
/*
|
|
||||||
* location is the only usefull new data item.
|
|
||||||
* For our devices it was available for ages via:
|
|
||||||
* - The legacy "/proc/xpp/XBUS-??/summary" (CONNECTOR=...)
|
|
||||||
* - The same info in "/proc/xpp/xbuses"
|
|
||||||
* - The modern "/sys/bus/astribanks/devices/xbus-??/connector" attribute
|
|
||||||
* So let's also export it via the newfangled "location" field.
|
|
||||||
*/
|
|
||||||
snprintf(span->location, sizeof(span->location) - 1, "%s", xbus->connector);
|
|
||||||
/*
|
|
||||||
* Who said a span and irq have 1-1 relationship?
|
|
||||||
* Also exporting this low-level detail isn't too wise.
|
|
||||||
* No irq's for you today!
|
|
||||||
*/
|
|
||||||
span->irq = 0;
|
|
||||||
|
|
||||||
snprintf(PHONEDEV(xpd).span.desc, MAX_SPANDESC, "Xorcom XPD #%02d/%1d%1d: %s",
|
|
||||||
xbus->num, xpd->addr.unit, xpd->addr.subunit, xpd->type_name);
|
|
||||||
XPD_DBG(GENERAL, xpd, "Registering span '%s'\n", PHONEDEV(xpd).span.desc);
|
XPD_DBG(GENERAL, xpd, "Registering span '%s'\n", PHONEDEV(xpd).span.desc);
|
||||||
CALL_PHONE_METHOD(card_dahdi_preregistration, xpd, 1);
|
CALL_PHONE_METHOD(card_dahdi_preregistration, xpd, 1);
|
||||||
if(dahdi_register(&PHONEDEV(xpd).span, prefmaster)) {
|
return 0;
|
||||||
XPD_ERR(xpd, "Failed to dahdi_register span\n");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int xpd_dahdi_postregister(xpd_t *xpd)
|
||||||
|
{
|
||||||
|
int cn;
|
||||||
|
|
||||||
atomic_inc(&num_registered_spans);
|
atomic_inc(&num_registered_spans);
|
||||||
atomic_inc(&PHONEDEV(xpd).dahdi_registered);
|
atomic_inc(&PHONEDEV(xpd).dahdi_registered);
|
||||||
CALL_PHONE_METHOD(card_dahdi_postregistration, xpd, 1);
|
CALL_PHONE_METHOD(card_dahdi_postregistration, xpd, 1);
|
||||||
@ -1153,6 +1052,48 @@ int dahdi_register_xpd(xpd_t *xpd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try our best to make asterisk close all channels related to
|
||||||
|
* this Astribank:
|
||||||
|
* - Set span state to DAHDI_ALARM_NOTOPEN in all relevant spans.
|
||||||
|
* - Notify dahdi afterwards about spans (so it can see all changes at once).
|
||||||
|
* - Also send DAHDI_EVENT_REMOVED on all channels.
|
||||||
|
*/
|
||||||
|
void xpd_dahdi_preunregister(xpd_t *xpd)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
if (!xpd)
|
||||||
|
return;
|
||||||
|
XPD_DBG(DEVICES, xpd, "\n");
|
||||||
|
spin_lock_irqsave(&xpd->lock, flags);
|
||||||
|
xpd->card_present = 0;
|
||||||
|
xpd_setstate(xpd, XPD_STATE_NOHW);
|
||||||
|
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||||
|
update_xpd_status(xpd, DAHDI_ALARM_NOTOPEN);
|
||||||
|
if(xpd->card_present)
|
||||||
|
CALL_PHONE_METHOD(card_dahdi_preregistration, xpd, 0);
|
||||||
|
/* Now notify dahdi */
|
||||||
|
if(SPAN_REGISTERED(xpd)) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
dahdi_alarm_notify(&PHONEDEV(xpd).span);
|
||||||
|
XPD_DBG(DEVICES, xpd, "Queuing DAHDI_EVENT_REMOVED on all channels to ask user to release them\n");
|
||||||
|
for (j=0; j<PHONEDEV(xpd).span.channels; j++) {
|
||||||
|
dahdi_qevent_lock(XPD_CHAN(xpd, j),DAHDI_EVENT_REMOVED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void xpd_dahdi_postunregister(xpd_t *xpd)
|
||||||
|
{
|
||||||
|
if (!xpd)
|
||||||
|
return;
|
||||||
|
atomic_dec(&PHONEDEV(xpd).dahdi_registered);
|
||||||
|
atomic_dec(&num_registered_spans);
|
||||||
|
if(xpd->card_present)
|
||||||
|
CALL_PHONE_METHOD(card_dahdi_postregistration, xpd, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------- Initialization -------------------------*/
|
/*------------------------- Initialization -------------------------*/
|
||||||
|
|
||||||
static void do_cleanup(void)
|
static void do_cleanup(void)
|
||||||
@ -1217,7 +1158,6 @@ EXPORT_SYMBOL(get_xpd);
|
|||||||
EXPORT_SYMBOL(put_xpd);
|
EXPORT_SYMBOL(put_xpd);
|
||||||
EXPORT_SYMBOL(xpd_alloc);
|
EXPORT_SYMBOL(xpd_alloc);
|
||||||
EXPORT_SYMBOL(xpd_free);
|
EXPORT_SYMBOL(xpd_free);
|
||||||
EXPORT_SYMBOL(xbus_request_removal);
|
|
||||||
EXPORT_SYMBOL(update_xpd_status);
|
EXPORT_SYMBOL(update_xpd_status);
|
||||||
EXPORT_SYMBOL(oht_pcm);
|
EXPORT_SYMBOL(oht_pcm);
|
||||||
EXPORT_SYMBOL(mark_offhook);
|
EXPORT_SYMBOL(mark_offhook);
|
||||||
|
@ -25,9 +25,10 @@
|
|||||||
#include "xpd.h"
|
#include "xpd.h"
|
||||||
#include "xproto.h"
|
#include "xproto.h"
|
||||||
|
|
||||||
int dahdi_register_xpd(xpd_t *xpd);
|
int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset);
|
||||||
int dahdi_unregister_xpd(xpd_t *xpd);
|
int xpd_dahdi_postregister(xpd_t *xpd);
|
||||||
void xbus_request_removal(xbus_t *xbus);
|
void xpd_dahdi_preunregister(xpd_t *xpd);
|
||||||
|
void xpd_dahdi_postunregister(xpd_t *xpd);
|
||||||
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
|
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
|
||||||
int unit, int subunit, byte type, byte subtype, int subunits, int subunit_ports, byte port_dir);
|
int unit, int subunit, byte type, byte subtype, int subunits, int subunit_ports, byte port_dir);
|
||||||
void xpd_post_init(xpd_t *xpd);
|
void xpd_post_init(xpd_t *xpd);
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
#include <linux/config.h>
|
#include <linux/config.h>
|
||||||
#endif
|
#endif
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/kobject.h>
|
#include <linux/device.h>
|
||||||
#include <linux/ioctl.h>
|
#include <linux/ioctl.h>
|
||||||
|
|
||||||
#ifdef CONFIG_DAHDI_NET
|
#ifdef CONFIG_DAHDI_NET
|
||||||
@ -885,6 +885,26 @@ struct dahdi_span_ops {
|
|||||||
|
|
||||||
/*! Opt: Provide the name of the echo canceller on a channel */
|
/*! Opt: Provide the name of the echo canceller on a channel */
|
||||||
const char *(*echocan_name)(const struct dahdi_chan *chan);
|
const char *(*echocan_name)(const struct dahdi_chan *chan);
|
||||||
|
|
||||||
|
/*! When using "pinned_spans", this function is called back when this
|
||||||
|
* span has been assigned with the system. */
|
||||||
|
void (*assigned)(struct dahdi_span *span);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dahdi_device - Represents a device that can contain one or more spans.
|
||||||
|
*
|
||||||
|
* @spans: List of child spans.
|
||||||
|
* @manufacturer: Device manufacturer.
|
||||||
|
* @location: The location of this device
|
||||||
|
* @devicetype: What type of device this is.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct dahdi_device {
|
||||||
|
struct list_head spans;
|
||||||
|
const char *manufacturer;
|
||||||
|
const char *location;
|
||||||
|
const char *devicetype;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dahdi_span {
|
struct dahdi_span {
|
||||||
@ -892,9 +912,6 @@ struct dahdi_span {
|
|||||||
char name[40]; /*!< Span name */
|
char name[40]; /*!< Span name */
|
||||||
char desc[80]; /*!< Span description */
|
char desc[80]; /*!< Span description */
|
||||||
const char *spantype; /*!< span type in text form */
|
const char *spantype; /*!< span type in text form */
|
||||||
const char *manufacturer; /*!< span's device manufacturer */
|
|
||||||
char devicetype[80]; /*!< span's device type */
|
|
||||||
char location[40]; /*!< span device's location in system */
|
|
||||||
int deflaw; /*!< Default law (DAHDI_MULAW or DAHDI_ALAW) */
|
int deflaw; /*!< Default law (DAHDI_MULAW or DAHDI_ALAW) */
|
||||||
int alarms; /*!< Pending alarms on span */
|
int alarms; /*!< Pending alarms on span */
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -933,7 +950,10 @@ struct dahdi_span {
|
|||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
struct proc_dir_entry *proc_entry;
|
struct proc_dir_entry *proc_entry;
|
||||||
#endif
|
#endif
|
||||||
struct list_head node;
|
struct list_head spans_node;
|
||||||
|
|
||||||
|
struct dahdi_device *parent;
|
||||||
|
struct list_head device_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dahdi_transcoder_channel {
|
struct dahdi_transcoder_channel {
|
||||||
@ -1031,6 +1051,7 @@ struct dahdi_dynamic {
|
|||||||
long rxjif;
|
long rxjif;
|
||||||
unsigned short txcnt;
|
unsigned short txcnt;
|
||||||
unsigned short rxcnt;
|
unsigned short rxcnt;
|
||||||
|
struct dahdi_device *ddev;
|
||||||
struct dahdi_span span;
|
struct dahdi_span span;
|
||||||
struct dahdi_chan *chans[256];
|
struct dahdi_chan *chans[256];
|
||||||
struct dahdi_dynamic_driver *driver;
|
struct dahdi_dynamic_driver *driver;
|
||||||
@ -1038,6 +1059,7 @@ struct dahdi_dynamic {
|
|||||||
int timing;
|
int timing;
|
||||||
int master;
|
int master;
|
||||||
unsigned char *msgbuf;
|
unsigned char *msgbuf;
|
||||||
|
struct device *dev;
|
||||||
|
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
};
|
};
|
||||||
@ -1131,10 +1153,11 @@ void dahdi_hdlc_putbuf(struct dahdi_chan *ss, unsigned char *rxb, int bytes);
|
|||||||
* and 1 if the currently transmitted message is now done */
|
* and 1 if the currently transmitted message is now done */
|
||||||
int dahdi_hdlc_getbuf(struct dahdi_chan *ss, unsigned char *bufptr, unsigned int *size);
|
int dahdi_hdlc_getbuf(struct dahdi_chan *ss, unsigned char *bufptr, unsigned int *size);
|
||||||
|
|
||||||
|
/*! Register a device. Returns 0 on success, -1 on failure. */
|
||||||
/*! Register a span. Returns 0 on success, -1 on failure. Pref-master is non-zero if
|
struct dahdi_device *dahdi_create_device(void);
|
||||||
we should have preference in being the master device */
|
int dahdi_register_device(struct dahdi_device *ddev, struct device *parent);
|
||||||
int dahdi_register(struct dahdi_span *span, int prefmaster);
|
void dahdi_unregister_device(struct dahdi_device *ddev);
|
||||||
|
void dahdi_free_device(struct dahdi_device *ddev);
|
||||||
|
|
||||||
/*! Allocate / free memory for a transcoder */
|
/*! Allocate / free memory for a transcoder */
|
||||||
struct dahdi_transcoder *dahdi_transcoder_alloc(int numchans);
|
struct dahdi_transcoder *dahdi_transcoder_alloc(int numchans);
|
||||||
@ -1149,9 +1172,6 @@ int dahdi_transcoder_unregister(struct dahdi_transcoder *tc);
|
|||||||
/*! \brief Alert a transcoder */
|
/*! \brief Alert a transcoder */
|
||||||
int dahdi_transcoder_alert(struct dahdi_transcoder_channel *ztc);
|
int dahdi_transcoder_alert(struct dahdi_transcoder_channel *ztc);
|
||||||
|
|
||||||
/*! \brief Unregister a span */
|
|
||||||
int dahdi_unregister(struct dahdi_span *span);
|
|
||||||
|
|
||||||
/*! \brief Gives a name to an LBO */
|
/*! \brief Gives a name to an LBO */
|
||||||
const char *dahdi_lboname(int lbo);
|
const char *dahdi_lboname(int lbo);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user