[dahdi-commits] sruffell: linux/trunk r8123 - in /linux/trunk/drivers/dahdi: voicebus/ vpmadt...
SVN commits to the DAHDI project
dahdi-commits at lists.digium.com
Fri Feb 26 10:40:54 CST 2010
Author: sruffell
Date: Fri Feb 26 10:40:44 2010
New Revision: 8123
URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=8123
Log:
wctdm24xxp: Add support for Hx8 series cards.
The Hx8 series cards support BRI modules in addition to analog modules.
Added:
linux/trunk/drivers/dahdi/wctdm24xxp/xhfc.c (with props)
linux/trunk/drivers/dahdi/wctdm24xxp/xhfc.h (with props)
Modified:
linux/trunk/drivers/dahdi/voicebus/voicebus.c
linux/trunk/drivers/dahdi/voicebus/voicebus.h
linux/trunk/drivers/dahdi/vpmadt032_loader/dahdi_vpmadt032_loader.c
linux/trunk/drivers/dahdi/wctdm24xxp/Kbuild
linux/trunk/drivers/dahdi/wctdm24xxp/base.c
linux/trunk/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
linux/trunk/drivers/dahdi/wcte12xp/base.c
Modified: linux/trunk/drivers/dahdi/voicebus/voicebus.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/voicebus/voicebus.c?view=diff&rev=8123&r1=8122&r2=8123
==============================================================================
--- linux/trunk/drivers/dahdi/voicebus/voicebus.c (original)
+++ linux/trunk/drivers/dahdi/voicebus/voicebus.c Fri Feb 26 10:40:44 2010
@@ -95,10 +95,11 @@
#define OWN_BIT (1 << 31)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
-static kmem_cache_t *buffer_cache;
+kmem_cache_t *voicebus_vbb_cache;
#else
-static struct kmem_cache *buffer_cache;
-#endif
+struct kmem_cache *voicebus_vbb_cache;
+#endif
+EXPORT_SYMBOL(voicebus_vbb_cache);
/* In memory structure shared by the host and the adapter. */
struct voicebus_descriptor {
@@ -365,8 +366,6 @@
struct voicebus_descriptor *d;
unsigned long flags;
- WARN_ON(!vb_is_stopped(vb));
-
spin_lock_irqsave(&vb->lock, flags);
for (i = 0; i < DRING_SIZE; ++i) {
d = vb_descriptor(dl, i);
@@ -374,7 +373,7 @@
WARN_ON(!dl->pending[i]);
dma_unmap_single(&vb->pdev->dev, d->buffer1,
VOICEBUS_SFRAME_SIZE, DMA_TO_DEVICE);
- voicebus_free(vb, dl->pending[i]);
+ kmem_cache_free(voicebus_vbb_cache, dl->pending[i]);
}
if (!test_bit(VOICEBUS_NORMAL_MODE, &vb->flags)) {
d->buffer1 = 0;
@@ -388,8 +387,6 @@
}
}
- /* Send out two idle buffers to start because sometimes the first buffer
- * doesn't make it back to us. */
dl->head = dl->tail = 0;
spin_unlock_irqrestore(&vb->lock, flags);
atomic_set(&dl->count, 0);
@@ -402,8 +399,6 @@
struct voicebus_descriptor_list *dl = &vb->rxd;
struct voicebus_descriptor *d;
unsigned long flags;
-
- BUG_ON(!vb_is_stopped(vb));
spin_lock_irqsave(&vb->lock, flags);
for (i = 0; i < DRING_SIZE; ++i) {
@@ -413,7 +408,7 @@
VOICEBUS_SFRAME_SIZE, DMA_FROM_DEVICE);
d->buffer1 = 0;
BUG_ON(!dl->pending[i]);
- kmem_cache_free(buffer_cache, dl->pending[i]);
+ kmem_cache_free(voicebus_vbb_cache, dl->pending[i]);
dl->pending[i] = NULL;
}
d->des0 &= ~OWN_BIT;
@@ -533,7 +528,7 @@
unsigned long timeout;
u32 reg;
u32 pci_access;
- const u32 DEFAULT_PCI_ACCESS = 0xfff80002;
+ const u32 DEFAULT_PCI_ACCESS = 0xfffc0002;
u8 cache_line_size;
BUG_ON(in_interrupt());
@@ -601,7 +596,7 @@
if (unlikely(d->buffer1)) {
/* Do not overwrite a buffer that is still in progress. */
WARN_ON(1);
- voicebus_free(vb, vbb);
+ kmem_cache_free(voicebus_vbb_cache, vbb);
return -EBUSY;
}
@@ -614,6 +609,49 @@
return 0;
}
+/**
+ * voicebus_transmit - Queue a buffer on the hardware descriptor ring.
+ *
+ */
+int voicebus_transmit(struct voicebus *vb, struct vbb *vbb)
+{
+ struct voicebus_descriptor *d;
+ struct voicebus_descriptor_list *dl = &vb->txd;
+
+ d = vb_descriptor(dl, dl->tail);
+
+ if (unlikely((d->buffer1 != vb->idle_vbb_dma_addr) && d->buffer1)) {
+ if (printk_ratelimit())
+ dev_warn(&vb->pdev->dev, "Dropping tx buffer buffer\n");
+ kmem_cache_free(voicebus_vbb_cache, vbb);
+ /* Schedule the underrun handler to run here, since we'll need
+ * to cleanup as best we can. */
+ schedule_work(&vb->underrun_work);
+ return -EFAULT;
+ }
+
+ dl->pending[dl->tail] = vbb;
+ d->buffer1 = dma_map_single(&vb->pdev->dev, vbb->data,
+ sizeof(vbb->data), DMA_TO_DEVICE);
+ dl->tail = (++(dl->tail)) & DRING_MASK;
+ SET_OWNED(d); /* That's it until the hardware is done with it. */
+ atomic_inc(&dl->count);
+ return 0;
+}
+EXPORT_SYMBOL(voicebus_transmit);
+
+
+/*!
+ * \brief Instruct the hardware to check for a new tx descriptor.
+ */
+static inline void
+__vb_tx_demand_poll(struct voicebus *vb)
+{
+ u32 status = __vb_getctl(vb, 0x0028);
+ if ((status & 0x00700000) == 0x00600000)
+ __vb_setctl(vb, 0x0008, 0x00000000);
+}
+
static void setup_descriptors(struct voicebus *vb)
{
int i;
@@ -631,7 +669,7 @@
vb_setctl(vb, 0x0018, (u32)vb->rxd.desc_dma);
for (i = 0; i < DRING_SIZE; ++i) {
- vbb = kmem_cache_alloc(buffer_cache, GFP_KERNEL);
+ vbb = kmem_cache_alloc(voicebus_vbb_cache, GFP_KERNEL);
if (unlikely(NULL == vbb))
BUG_ON(1);
list_add_tail(&vbb->entry, &buffers);
@@ -646,13 +684,13 @@
if (test_bit(VOICEBUS_NORMAL_MODE, &vb->flags)) {
for (i = 0; i < vb->min_tx_buffer_count; ++i) {
- vbb = kmem_cache_alloc(buffer_cache, GFP_KERNEL);
+ vbb = kmem_cache_alloc(voicebus_vbb_cache, GFP_KERNEL);
if (unlikely(NULL == vbb))
BUG_ON(1);
else
list_add_tail(&vbb->entry, &buffers);
}
-
+
tasklet_disable(&vb->tasklet);
handle_transmit(vb, &buffers);
tasklet_enable(&vb->tasklet);
@@ -739,55 +777,6 @@
printk(KERN_DEBUG "\n\n");
}
#endif
-
-/**
- * voicebus_transmit - Queue a buffer on the hardware descriptor ring.
- *
- */
-static int __voicebus_transmit(struct voicebus *vb, struct vbb *vbb)
-{
- struct voicebus_descriptor *d;
- struct voicebus_descriptor_list *dl = &vb->txd;
-
- d = vb_descriptor(dl, dl->tail);
-
- if (unlikely((d->buffer1 != vb->idle_vbb_dma_addr) && d->buffer1)) {
- if (printk_ratelimit())
- dev_warn(&vb->pdev->dev, "Dropping tx buffer buffer\n");
- voicebus_free(vb, vbb);
- /* Schedule the underrun handler to run here, since we'll need
- * to cleanup as best we can. */
- schedule_work(&vb->underrun_work);
- return -EFAULT;
- }
-
- dl->pending[dl->tail] = vbb;
- d->buffer1 = dma_map_single(&vb->pdev->dev, vbb->data,
- sizeof(vbb->data), DMA_TO_DEVICE);
- dl->tail = (++(dl->tail)) & DRING_MASK;
- SET_OWNED(d); /* That's it until the hardware is done with it. */
- atomic_inc(&dl->count);
- return 0;
-}
-
-/*!
- * \brief Instruct the hardware to check for a new tx descriptor.
- */
-static inline void
-__vb_tx_demand_poll(struct voicebus *vb)
-{
- u32 status = __vb_getctl(vb, 0x0028);
- if ((status & 0x00700000) == 0x00600000)
- __vb_setctl(vb, 0x0008, 0x00000000);
-}
-
-int voicebus_transmit(struct voicebus *vb, struct vbb *vbb)
-{
- __voicebus_transmit(vb, vbb);
- __vb_tx_demand_poll(vb);
- return 0;
-}
-EXPORT_SYMBOL(voicebus_transmit);
/*!
* \brief Remove the next completed transmit buffer (txb) from the tx
@@ -860,18 +849,6 @@
}
/*!
- * \brief Free a buffer for reuse.
- *
- */
-void
-voicebus_free(struct voicebus *vb, struct vbb *vbb)
-{
- kmem_cache_free(buffer_cache, vbb);
-}
-EXPORT_SYMBOL(voicebus_free);
-
-
-/*!
* \brief Command the hardware to check if it owns the next receive
* descriptor.
*/
@@ -925,11 +902,15 @@
/* Start the transmit and receive processors. */
reg = __vb_getctl(vb, 0x0030);
__vb_setctl(vb, 0x0030, reg|0x00002002);
- /* Tell the interface to poll the tx and rx descriptors. */
+ __vb_getctl(vb, 0x0030);
__vb_rx_demand_poll(vb);
__vb_tx_demand_poll(vb);
+ __vb_getctl(vb, 0x0030);
VBUNLOCK(vb);
}
+
+static void vb_tasklet_relaxed(unsigned long data);
+static void vb_tasklet(unsigned long data);
/*!
* \brief Starts the VoiceBus interface.
@@ -950,6 +931,11 @@
if (!vb_is_stopped(vb))
return -EBUSY;
+
+ if (test_bit(VOICEBUS_NORMAL_MODE, &vb->flags))
+ tasklet_init(&vb->tasklet, vb_tasklet, (unsigned long)vb);
+ else
+ tasklet_init(&vb->tasklet, vb_tasklet_relaxed, (unsigned long)vb);
ret = vb_reset_interface(vb);
if (ret)
@@ -1108,7 +1094,7 @@
/* Set the minimum latency in case we're restarted...we don't want to
* wait for the buffer to grow to this depth again in that case. */
for (i = 0; i < increase; ++i) {
- vbb = kmem_cache_alloc(buffer_cache, GFP_ATOMIC);
+ vbb = kmem_cache_alloc(voicebus_vbb_cache, GFP_ATOMIC);
WARN_ON(NULL == vbb);
if (likely(NULL != vbb))
list_add_tail(&vbb->entry, &local);
@@ -1127,29 +1113,64 @@
vb->min_tx_buffer_count += increase;
}
-static void vb_set_all_owned(struct voicebus *vb,
- struct voicebus_descriptor_list *dl)
-{
- int i;
- struct voicebus_descriptor *d;
-
- for (i = 0; i < DRING_SIZE; ++i) {
- d = vb_descriptor(dl, i);
- SET_OWNED(d);
- }
-}
-
-static inline void vb_set_all_tx_owned(struct voicebus *vb)
-{
- vb_set_all_owned(vb, &vb->txd);
-}
-
/**
- * vb_deferred() - Manage the transmit and receive descriptor rings.
- *
- */
-static void vb_deferred(struct voicebus *vb)
-{
+ * vb_tasklet_relaxed() - Service the rings without strict timing requierments.
+ *
+ */
+static void vb_tasklet_relaxed(unsigned long data)
+{
+ struct voicebus *vb = (struct voicebus *)data;
+ LIST_HEAD(buffers);
+ struct vbb *vbb;
+ const int DEFAULT_COUNT = 5;
+ int count = DEFAULT_COUNT;
+ u32 des0 = 0;
+
+ /* First, temporarily store any non-idle buffers that the hardware has
+ * indicated it's finished transmitting. Non idle buffers are those
+ * buffers that contain actual data and was filled out by the client
+ * driver (as of this writing, the wcte12xp or wctdm24xxp drivers) when
+ * passed up through the handle_transmit callback.
+ *
+ * On the other hand, idle buffers are "dummy" buffers that solely exist
+ * to in order to prevent the transmit descriptor ring from ever
+ * completely draining. */
+ while ((vbb = vb_get_completed_txb(vb)))
+ list_add_tail(&vbb->entry, &vb->tx_complete);
+
+ while (--count && !list_empty(&vb->tx_complete))
+ list_move_tail(vb->tx_complete.next, &buffers);
+
+ /* Prep all the new buffers for transmit before actually sending any
+ * of them. */
+ handle_transmit(vb, &buffers);
+
+ list_for_each_entry(vbb, &buffers, entry)
+ voicebus_transmit(vb, vbb);
+ INIT_LIST_HEAD(&buffers);
+
+ /* If there may still be buffers in the descriptor rings, reschedule
+ * ourself to run again. We essentially yield here to allow any other
+ * cards a chance to run. */
+ if (unlikely(!count && !test_bit(VOICEBUS_STOP, &vb->flags)))
+ tasklet_hi_schedule(&vb->tasklet);
+
+ /* And finally, pass up any receive buffers. */
+ count = DEFAULT_COUNT;
+ while (--count && (vbb = vb_get_completed_rxb(vb, &des0))) {
+ if (((des0 >> 16) & 0x7fff) == VOICEBUS_SFRAME_SIZE)
+ list_add_tail(&vbb->entry, &buffers);
+ }
+
+ handle_receive(vb, &buffers);
+ list_for_each_entry(vbb, &buffers, entry)
+ vb_submit_rxb(vb, vbb);
+ return;
+}
+
+static void vb_tasklet(unsigned long data)
+{
+ struct voicebus *vb = (struct voicebus *)data;
int softunderrun;
LIST_HEAD(buffers);
struct vbb *vbb;
@@ -1277,13 +1298,8 @@
/* And finally, pass up any receive buffers. */
count = DEFAULT_COUNT;
while (--count && (vbb = vb_get_completed_rxb(vb, &des0))) {
- if (((des0 >> 16) & 0x7fff) != VOICEBUS_SFRAME_SIZE) {
- dev_dbg(&vb->pdev->dev,
- "ERROR: Dropping packet of wrong size. (%d)\n",
- (des0>>16)&0x7fff);
- } else {
+ if (((des0 >> 16) & 0x7fff) == VOICEBUS_SFRAME_SIZE)
list_add_tail(&vbb->entry, &buffers);
- }
}
handle_receive(vb, &buffers);
@@ -1297,7 +1313,7 @@
while (!list_empty(&buffers)) {
vbb = list_entry(buffers.next, struct vbb, entry);
list_del(&vbb->entry);
- kmem_cache_free(buffer_cache, vbb);
+ kmem_cache_free(voicebus_vbb_cache, vbb);
}
return;
}
@@ -1365,7 +1381,8 @@
if (unlikely((int_status &
(TX_UNAVAILABLE_INTERRUPT|RX_UNAVAILABLE_INTERRUPT)) &&
- !test_bit(VOICEBUS_STOP, &vb->flags))) {
+ !test_bit(VOICEBUS_STOP, &vb->flags) &&
+ test_bit(VOICEBUS_NORMAL_MODE, &vb->flags))) {
schedule_work(&vb->underrun_work);
__vb_setctl(vb, SR_CSR5, int_status);
} else if (likely(int_status &
@@ -1422,12 +1439,6 @@
}
#endif
-static void vb_tasklet(unsigned long data)
-{
- struct voicebus *vb = (struct voicebus *)data;
- vb_deferred(vb);
-}
-
/*!
* \brief Initalize the voicebus interface.
*
@@ -1462,7 +1473,6 @@
vb->min_tx_buffer_count = VOICEBUS_DEFAULT_LATENCY;
INIT_LIST_HEAD(&vb->tx_complete);
- tasklet_init(&vb->tasklet, vb_tasklet, (unsigned long)vb);
#if defined(CONFIG_VOICEBUS_TIMER)
init_timer(&vb->timer);
@@ -1672,7 +1682,7 @@
int res;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
- buffer_cache = kmem_cache_create(THIS_MODULE->name,
+ voicebus_vbb_cache = kmem_cache_create(THIS_MODULE->name,
sizeof(struct vbb), 0,
#if defined(CONFIG_SLUB) && (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 22))
SLAB_HWCACHE_ALIGN |
@@ -1684,18 +1694,18 @@
#endif
#else
#if (defined(DEBUG) && defined(CONFIG_SLAB_DEBUG))
- buffer_cache = kmem_cache_create(THIS_MODULE->name,
+ voicebus_vbb_cache = kmem_cache_create(THIS_MODULE->name,
sizeof(struct vbb), 0,
SLAB_HWCACHE_ALIGN | SLAB_STORE_USER |
SLAB_POISON | SLAB_DEBUG_FREE, NULL);
#else
- buffer_cache = kmem_cache_create(THIS_MODULE->name,
+ voicebus_vbb_cache = kmem_cache_create(THIS_MODULE->name,
sizeof(struct vbb), 0,
SLAB_HWCACHE_ALIGN, NULL);
#endif
#endif
- if (NULL == buffer_cache) {
+ if (NULL == voicebus_vbb_cache) {
printk(KERN_ERR "%s: Failed to allocate buffer cache.\n",
THIS_MODULE->name);
return -ENOMEM;
@@ -1715,7 +1725,7 @@
static void __exit voicebus_module_cleanup(void)
{
- kmem_cache_destroy(buffer_cache);
+ kmem_cache_destroy(voicebus_vbb_cache);
WARN_ON(!list_empty(&binary_loader_list));
}
Modified: linux/trunk/drivers/dahdi/voicebus/voicebus.h
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/voicebus/voicebus.h?view=diff&rev=8123&r1=8122&r2=8123
==============================================================================
--- linux/trunk/drivers/dahdi/voicebus/voicebus.h (original)
+++ linux/trunk/drivers/dahdi/voicebus/voicebus.h Fri Feb 26 10:40:44 2010
@@ -132,12 +132,17 @@
#endif
};
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+extern kmem_cache_t *voicebus_vbb_cache;
+#else
+extern struct kmem_cache *voicebus_vbb_cache;
+#endif
+
int __voicebus_init(struct voicebus *vb, const char *board_name,
int normal_mode);
void voicebus_release(struct voicebus *vb);
int voicebus_start(struct voicebus *vb);
int voicebus_stop(struct voicebus *vb);
-void voicebus_free(struct voicebus *vb, struct vbb *vbb);
int voicebus_transmit(struct voicebus *vb, struct vbb *vbb);
int voicebus_set_minlatency(struct voicebus *vb, unsigned int milliseconds);
int voicebus_current_latency(struct voicebus *vb);
Modified: linux/trunk/drivers/dahdi/vpmadt032_loader/dahdi_vpmadt032_loader.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/vpmadt032_loader/dahdi_vpmadt032_loader.c?view=diff&rev=8123&r1=8122&r2=8123
==============================================================================
--- linux/trunk/drivers/dahdi/vpmadt032_loader/dahdi_vpmadt032_loader.c (original)
+++ linux/trunk/drivers/dahdi/vpmadt032_loader/dahdi_vpmadt032_loader.c Fri Feb 26 10:40:44 2010
@@ -105,15 +105,20 @@
struct private_context *ctx;
const struct voicebus_operations *old;
void *old_drvdata;
+ int id;
might_sleep();
ctx = kzalloc(sizeof(struct private_context), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
init_private_context(ctx);
ctx->vb = vb;
- ret = __vpmadt032_start_load(
- 0, vb->pdev->vendor << 16 | vb->pdev->device,
- &ctx->pvt);
+
+ if (0x8007 == vb->pdev->device || 0x8008 == vb->pdev->device)
+ id = vb->pdev->vendor << 16 | 0x2400;
+ else
+ id = vb->pdev->vendor << 16 | vb->pdev->device;
+
+ ret = __vpmadt032_start_load(0, id, &ctx->pvt);
if (ret)
goto error_exit;
old_drvdata = pci_get_drvdata(vb->pdev);
Modified: linux/trunk/drivers/dahdi/wctdm24xxp/Kbuild
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/wctdm24xxp/Kbuild?view=diff&rev=8123&r1=8122&r2=8123
==============================================================================
--- linux/trunk/drivers/dahdi/wctdm24xxp/Kbuild (original)
+++ linux/trunk/drivers/dahdi/wctdm24xxp/Kbuild Fri Feb 26 10:40:44 2010
@@ -2,4 +2,4 @@
EXTRA_CFLAGS += -I$(src)/.. -Wno-undef
-wctdm24xxp-objs := base.o
+wctdm24xxp-objs := base.o xhfc.o
Modified: linux/trunk/drivers/dahdi/wctdm24xxp/base.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/wctdm24xxp/base.c?view=diff&rev=8123&r1=8122&r2=8123
==============================================================================
--- linux/trunk/drivers/dahdi/wctdm24xxp/base.c (original)
+++ linux/trunk/drivers/dahdi/wctdm24xxp/base.c Fri Feb 26 10:40:44 2010
@@ -3,6 +3,9 @@
*
* Written by Mark Spencer <markster at digium.com>
* Support for TDM800P and VPM150M by Matthew Fredrickson <creslin at digium.com>
+ *
+ * Support for Hx8 by Andrew Kohlsmith <akohlsmith at mixdown.ca> and Matthew
+ * Fredrickson <creslin at digium.com>
*
* Copyright (C) 2005 - 2010 Digium, Inc.
* All rights reserved.
@@ -34,6 +37,8 @@
Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db
*/
+#define DEBUG
+
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -46,11 +51,13 @@
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
+#include <linux/firmware.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#include <linux/semaphore.h>
#else
#include <asm/semaphore.h>
#endif
+#include <linux/crc32.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
/* Define this if you would like to load the modules in parallel. While this
@@ -68,6 +75,7 @@
#include "proslic.h"
#include "wctdm24xxp.h"
+#include "xhfc.h"
#include "adt_lec.h"
@@ -187,10 +195,24 @@
static const struct wctdm_desc wcaex2400 = { "Wildcard AEX2400", FLAG_EXPRESS, 24 };
static const struct wctdm_desc wcaex800 = { "Wildcard AEX800", FLAG_EXPRESS, 8 };
static const struct wctdm_desc wcaex410 = { "Wildcard AEX410", FLAG_EXPRESS, 4 };
-
+static const struct wctdm_desc wcha80000 = { "HA8-0000", 0, 8 };
+static const struct wctdm_desc wchb80000 = { "HB8-0000", FLAG_EXPRESS, 8 };
+
+/**
+ * Returns true if the card is one of the Hybrid Digital Analog Cards.
+ */
+static inline bool is_hx8(const struct wctdm *wc)
+{
+ return (&wcha80000 == wc->desc) || (&wchb80000 == wc->desc);
+}
+
+static inline bool is_digital_span(const struct wctdm_span *wspan)
+{
+ return (wspan->span.linecompat > 0);
+}
struct wctdm *ifaces[WC_MAX_IFACES];
-spinlock_t ifacelock = SPIN_LOCK_UNLOCKED;
+DECLARE_MUTEX(ifacelock);
static void wctdm_release(struct wctdm *wc);
@@ -215,6 +237,7 @@
static int ringdebounce = DEFAULT_RING_DEBOUNCE;
static int fwringdetect = 0;
static int latency = VOICEBUS_DEFAULT_LATENCY;
+static int forceload;
#define MS_PER_HOOKCHECK (1)
#define NEONMWI_ON_DEBOUNCE (100/MS_PER_HOOKCHECK)
@@ -291,7 +314,7 @@
static inline int empty_slot(struct wctdm *wc, int card)
{
int x;
- for (x=0;x<USER_COMMANDS;x++) {
+ for (x = 0; x < USER_COMMANDS; x++) {
if (!wc->cmdq[card].cmds[x])
return x;
}
@@ -438,8 +461,7 @@
vpm->curecstate[i].nlp_type = vpm->options.vpmnlptype;
vpm->curecstate[i].nlp_threshold = vpm->options.vpmnlpthresh;
vpm->curecstate[i].nlp_max_suppress = vpm->options.vpmnlpmaxsupp;
- vpm->curecstate[i].companding = (wc->span.deflaw == DAHDI_LAW_MULAW) ? ADT_COMP_ULAW : ADT_COMP_ALAW;
-
+ vpm->curecstate[i].companding = (wc->chans[i]->chan.span->deflaw == DAHDI_LAW_ALAW) ? ADT_COMP_ALAW : ADT_COMP_ULAW;
/* set_vpmadt032_chanconfig_from_state(&vpm->curecstate[i], &vpm->options, i, &chanconfig); !!! */
vpm->setchanconfig_from_state(vpm, i, &chanconfig);
if ((res = gpakConfigureChannel(vpm->dspid, i, tdmToTdm, &chanconfig, &cstatus))) {
@@ -485,6 +507,7 @@
static inline void cmd_dequeue_vpmadt032(struct wctdm *wc, u8 *writechunk, int whichframe)
{
+ unsigned long flags;
struct vpmadt032_cmd *curcmd = NULL;
struct vpmadt032 *vpmadt032 = wc->vpmadt032;
int x;
@@ -496,6 +519,7 @@
if (test_bit(VPM150M_SPIRESET, &vpmadt032->control) || test_bit(VPM150M_HPIRESET, &vpmadt032->control)) {
if (debug & DEBUG_ECHOCAN)
dev_info(&wc->vb.pdev->dev, "HW Resetting VPMADT032...\n");
+ spin_lock_irqsave(&wc->reglock, flags);
for (x = 24; x < 28; x++) {
if (x == 24) {
if (test_and_clear_bit(VPM150M_SPIRESET, &vpmadt032->control))
@@ -507,6 +531,7 @@
writechunk[CMD_BYTE(x, 1, 0)] = 0;
writechunk[CMD_BYTE(x, 2, 0)] = 0x00;
}
+ spin_unlock_irqrestore(&wc->reglock, flags);
return;
}
@@ -603,39 +628,37 @@
ecval = ecval % EC_SIZE;
#endif
- /* if a QRV card, map it to its first channel */
- if ((wc->modtype[card] == MOD_TYPE_QRV) && (card & 3))
- {
- return;
- }
- if (wc->altcs[card])
- subaddr = 0;
-
-
-
+ /* QRV and BRI modules only use commands relating to the first channel */
+ if ((card & 0x03) && (wc->modtype[card] == MOD_TYPE_QRV)) {
+ return;
+ }
+
+ if (wc->altcs[card])
+ subaddr = 0;
+
/* Skip audio */
writechunk += 24;
spin_lock_irqsave(&wc->reglock, flags);
/* Search for something waiting to transmit */
if (pos) {
- for (x=0;x<MAX_COMMANDS;x++) {
+ for (x = 0; x < MAX_COMMANDS; x++) {
if ((wc->cmdq[card].cmds[x] & (__CMD_RD | __CMD_WR)) &&
!(wc->cmdq[card].cmds[x] & (__CMD_TX | __CMD_FIN))) {
curcmd = wc->cmdq[card].cmds[x];
-#if 0
- dev_info(&wc->vb.pdev->dev, "Transmitting command '%08x' in slot %d\n", wc->cmdq[card].cmds[x], wc->txident);
-#endif
wc->cmdq[card].cmds[x] |= (wc->txident << 24) | __CMD_TX;
break;
}
}
}
+
if (!curcmd) {
/* If nothing else, use filler */
if (wc->modtype[card] == MOD_TYPE_FXS)
curcmd = CMD_RD(LINE_STATE);
else if (wc->modtype[card] == MOD_TYPE_FXO)
curcmd = CMD_RD(12);
+ else if (wc->modtype[card] == MOD_TYPE_BRI)
+ curcmd = 0x101010;
else if (wc->modtype[card] == MOD_TYPE_QRV)
curcmd = CMD_RD(3);
else if (wc->modtype[card] == MOD_TYPE_VPM) {
@@ -649,13 +672,15 @@
curcmd = CMD_RD(0x1a0);
}
}
+
if (wc->modtype[card] == MOD_TYPE_FXS) {
- writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = (1 << (subaddr));
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = (1 << (subaddr));
if (curcmd & __CMD_WR)
- writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0x7f;
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0x7f;
else
- writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x80 | ((curcmd >> 8) & 0x7f);
- writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x80 | ((curcmd >> 8) & 0x7f);
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
+
} else if (wc->modtype[card] == MOD_TYPE_FXO) {
static const int FXO_ADDRS[4] = { 0x00, 0x08, 0x04, 0x0c };
int idx = CMD_BYTE(card, 0, wc->altcs[card]);
@@ -663,48 +688,53 @@
writechunk[idx] = 0x20 | FXO_ADDRS[subaddr];
else
writechunk[idx] = 0x60 | FXO_ADDRS[subaddr];
- writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff;
- writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff;
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
+
} else if (wc->modtype[card] == MOD_TYPE_FXSINIT) {
/* Special case, we initialize the FXS's into the three-byte command mode then
switch to the regular mode. To send it into thee byte mode, treat the path as
6 two-byte commands and in the last one we initialize register 0 to 0x80. All modules
read this as the command to switch to daisy chain mode and we're done. */
- writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
- writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00;
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00;
if ((card & 0x1) == 0x1)
- writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x80;
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x80;
else
- writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00;
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00;
+
+ } else if (wc->modtype[card] == MOD_TYPE_BRI) {
+
+ if (unlikely((curcmd != 0x101010) && (curcmd & 0x1010) == 0x1010)) /* b400m CPLD */
+ writechunk[CMD_BYTE(card, 0, 0)] = 0x55;
+ else /* xhfc */
+ writechunk[CMD_BYTE(card, 0, 0)] = 0x10;
+ writechunk[CMD_BYTE(card, 1, 0)] = (curcmd >> 8) & 0xff;
+ writechunk[CMD_BYTE(card, 2, 0)] = curcmd & 0xff;
} else if (wc->modtype[card] == MOD_TYPE_VPM) {
if (curcmd & __CMD_WR)
- writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xc | ((curcmd >> 16) & 0x1);
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xc | ((curcmd >> 16) & 0x1);
else
- writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xa | ((curcmd >> 16) & 0x1);
- writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff;
- writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
- } else if (wc->modtype[card] == MOD_TYPE_VPM150M) {
- ;
- } else if (wc->modtype[card] == MOD_TYPE_QRV) {
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xa | ((curcmd >> 16) & 0x1);
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff;
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
+ } else if (wc->modtype[card] == MOD_TYPE_QRV) {
- writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
- if (!curcmd)
- {
- writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00;
- writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00;
- }
- else
- {
- if (curcmd & __CMD_WR)
- writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x40 | ((curcmd >> 8) & 0x3f);
- else
- writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0xc0 | ((curcmd >> 8) & 0x3f);
- writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
- }
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
+ if (!curcmd) {
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00;
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00;
+ } else {
+ if (curcmd & __CMD_WR)
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x40 | ((curcmd >> 8) & 0x3f);
+ else
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0xc0 | ((curcmd >> 8) & 0x3f);
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
+ }
} else if (wc->modtype[card] == MOD_TYPE_NONE) {
- writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
- writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00;
- writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00;
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x10;
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x10;
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x10;
}
#if 0
/* XXX */
@@ -715,10 +745,10 @@
#if 0
/* XXX */
cmddesc++;
-#endif
-}
-
-static inline void cmd_decipher_vpmadt032(struct wctdm *wc, unsigned char *readchunk)
+#endif
+}
+
+static inline void cmd_decipher_vpmadt032(struct wctdm *wc, const u8 *readchunk)
{
unsigned long flags;
struct vpmadt032 *vpm = wc->vpmadt032;
@@ -747,6 +777,7 @@
/* Skip audio */
readchunk += 24;
+
/* Store result */
cmd->data = (0xff & readchunk[CMD_BYTE(25, 1, 0)]) << 8;
cmd->data |= readchunk[CMD_BYTE(25, 2, 0)];
@@ -757,26 +788,23 @@
cmd->desc |= __VPM150M_FIN;
complete(&cmd->complete);
}
-#if 0
- // if (printk_ratelimit())
- dev_info(&wc->vb.pdev->dev, "Received txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", cmd->txident, cmd->desc, cmd->address, cmd->data);
-#endif
-}
-
-static inline void cmd_decipher(struct wctdm *wc, u8 *readchunk, int card)
+}
+
+static inline void cmd_decipher(struct wctdm *wc, const u8 *readchunk, int card)
{
unsigned long flags;
unsigned char ident;
int x;
- /* if a QRV card, map it to its first channel */
- if ((wc->modtype[card] == MOD_TYPE_QRV) && (card & 3))
- {
+ /* QRV and BRI modules only use commands relating to the first channel */
+ if ((card & 0x03) && (wc->modtype[card] == MOD_TYPE_QRV)) { /* || (wc->modtype[card] == MOD_TYPE_BRI))) { */
return;
}
+
/* Skip audio */
readchunk += 24;
spin_lock_irqsave(&wc->reglock, flags);
+
/* Search for any pending results */
for (x=0;x<MAX_COMMANDS;x++) {
if ((wc->cmdq[card].cmds[x] & (__CMD_RD | __CMD_WR)) &&
@@ -787,6 +815,11 @@
/* Store result */
wc->cmdq[card].cmds[x] |= readchunk[CMD_BYTE(card, 2, wc->altcs[card])];
wc->cmdq[card].cmds[x] |= __CMD_FIN;
+/*
+ if (card == 0 && wc->cmdq[card].cmds[x] & __CMD_RD) {
+ dev_info(&wc->vb.pdev->dev, "decifer: got response %02x\n", wc->cmdq[card].cmds[x] & 0xff);
+ }
+*/
if (wc->cmdq[card].cmds[x] & __CMD_WR) {
/* Go ahead and clear out writes since they need no acknowledgement */
wc->cmdq[card].cmds[x] = 0x00000000;
@@ -819,6 +852,8 @@
wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(5); /* Hook/Ring state */
} else if (wc->modtype[card] == MOD_TYPE_QRV) {
wc->cmdq[card & 0xfc].cmds[USER_COMMANDS + 0] = CMD_RD(3); /* COR/CTCSS state */
+ } else if (wc->modtype[card] == MOD_TYPE_BRI) {
+ wc->cmdq[card].cmds[USER_COMMANDS + 0] = wctdm_bri_checkisr(wc, card, 0);
#ifdef VPM_SUPPORT
} else if (wc->modtype[card] == MOD_TYPE_VPM) {
wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(0xb9); /* DTMF interrupt */
@@ -836,6 +871,8 @@
wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(29); /* Battery */
} else if (wc->modtype[card] == MOD_TYPE_QRV) {
wc->cmdq[card & 0xfc].cmds[USER_COMMANDS + 1] = CMD_RD(3); /* Battery */
+ } else if (wc->modtype[card] == MOD_TYPE_BRI) {
+ wc->cmdq[card].cmds[USER_COMMANDS + 1] = wctdm_bri_checkisr(wc, card, 1);
#ifdef VPM_SUPPORT
} else if (wc->modtype[card] == MOD_TYPE_VPM) {
wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(0xbd); /* DTMF interrupt */
@@ -853,8 +890,8 @@
int i;
register u8 *chanchunk;
- for (i = 0; i < wc->cards; i += 4) {
- chanchunk = &wc->chans[0 + i]->writechunk[0];
+ for (i = 0; i < wc->avchannels; i += 4) {
+ chanchunk = &wc->chans[0 + i]->chan.writechunk[0];
sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0];
sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1];
sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2];
@@ -864,7 +901,7 @@
sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6];
sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7];
- chanchunk = &wc->chans[1 + i]->writechunk[0];
+ chanchunk = &wc->chans[1 + i]->chan.writechunk[0];
sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0];
sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1];
sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2];
@@ -874,7 +911,7 @@
sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6];
sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7];
- chanchunk = &wc->chans[2 + i]->writechunk[0];
+ chanchunk = &wc->chans[2 + i]->chan.writechunk[0];
sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0];
sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1];
sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2];
@@ -884,7 +921,7 @@
sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6];
sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7];
- chanchunk = &wc->chans[3 + i]->writechunk[0];
+ chanchunk = &wc->chans[3 + i]->chan.writechunk[0];
sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0];
sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1];
sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2];
@@ -899,30 +936,40 @@
static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char *writechunk)
{
int x,y;
+ struct dahdi_span *s;
/* Calculate Transmission */
if (likely(wc->initialized)) {
- dahdi_transmit(&wc->span);
+ for (x = 0; x < MAX_SPANS; x++) {
+ if (wc->spans[x]) {
+ s = &wc->spans[x]->span;
+ dahdi_transmit(s);
+ }
+ }
insert_tdm_data(wc, writechunk);
}
- for (x=0;x<DAHDI_CHUNKSIZE;x++) {
+ for (x = 0; x < DAHDI_CHUNKSIZE; x++) {
/* Send a sample, as a 32-bit word */
- for (y=0;y < wc->cards;y++) {
- if (!x) {
+
+ /* TODO: ABK: hmm, this was originally mods_per_board, but we
+ * need to worry about all the active "voice" timeslots, since
+ * BRI modules have a different number of TDM channels than
+ * installed modules. */
+ for (y = 0; y < wc->avchannels; y++) {
+ if (!x && y < wc->mods_per_board) {
cmd_checkisr(wc, y);
}
- if (x < 3)
+ if ((x < 3) && (y < wc->mods_per_board))
cmd_dequeue(wc, writechunk, y, x);
}
if (!x)
wc->blinktimer++;
if (wc->vpm100) {
- for (y=24;y<28;y++) {
- if (!x) {
+ for (y = NUM_MODULES; y < NUM_MODULES + NUM_EC; y++) {
+ if (!x)
cmd_checkisr(wc, y);
- }
cmd_dequeue(wc, writechunk, y, x);
}
#ifdef FANCY_ECHOCAN
@@ -939,7 +986,7 @@
writechunk[EFRAME_SIZE] = wc->ctlreg;
writechunk[EFRAME_SIZE + 1] = wc->txident++;
- if ((wc->desc->ports == 4) && ((wc->ctlreg & 0x10) || (wc->modtype[NUM_CARDS] == MOD_TYPE_NONE))) {
+ if ((wc->desc->ports == 4) && ((wc->ctlreg & 0x10) || (wc->modtype[NUM_MODULES] == MOD_TYPE_NONE))) {
writechunk[EFRAME_SIZE + 2] = 0;
for (y = 0; y < 4; y++) {
if (wc->modtype[y] == MOD_TYPE_NONE)
@@ -958,11 +1005,11 @@
int hit=0;
int ret;
- /* if a QRV card, use only its first channel */
- if (wc->modtype[card] == MOD_TYPE_QRV)
- {
- if (card & 3) return(0);
- }
+ /* QRV and BRI cards are only addressed at their first "port" */
+ if ((card & 0x03) && ((wc->modtype[card] == MOD_TYPE_QRV) ||
+ (wc->modtype[card] == MOD_TYPE_BRI)))
+ return 0;
+
do {
spin_lock_irqsave(&wc->reglock, flags);
hit = empty_slot(wc, card);
@@ -984,12 +1031,12 @@
{
return wctdm_setreg_full(wc, card, addr, val, 1);
}
-static inline int wctdm_setreg(struct wctdm *wc, int card, int addr, int val)
+inline int wctdm_setreg(struct wctdm *wc, int card, int addr, int val)
{
return wctdm_setreg_full(wc, card, addr, val, 0);
}
-static inline int wctdm_getreg(struct wctdm *wc, int card, int addr)
+inline int wctdm_getreg(struct wctdm *wc, int card, int addr)
{
unsigned long flags;
int hit;
@@ -1028,14 +1075,15 @@
return ret;
}
+
static inline unsigned char wctdm_vpm_in(struct wctdm *wc, int unit, const unsigned int addr)
{
- return wctdm_getreg(wc, unit + NUM_CARDS, addr);
+ return wctdm_getreg(wc, unit + NUM_MODULES, addr);
}
static inline void wctdm_vpm_out(struct wctdm *wc, int unit, const unsigned int addr, const unsigned char val)
{
- wctdm_setreg(wc, unit + NUM_CARDS, addr, val);
+ wctdm_setreg(wc, unit + NUM_MODULES, addr, val);
}
/* TODO: this should go in the dahdi_voicebus module... */
@@ -1055,6 +1103,7 @@
list_move_tail(&cmd->node, &vpmadt032->pending_cmds);
}
spin_unlock_irqrestore(&vpmadt032->list_lock, flags);
+
}
static inline void cmd_retransmit(struct wctdm *wc)
@@ -1064,9 +1113,11 @@
/* Force retransmissions */
spin_lock_irqsave(&wc->reglock, flags);
for (x=0;x<MAX_COMMANDS;x++) {
- for (y=0;y<wc->cards;y++) {
- if (!(wc->cmdq[y].cmds[x] & __CMD_FIN))
- wc->cmdq[y].cmds[x] &= ~(__CMD_TX | (0xff << 24));
+ for (y = 0; y < wc->mods_per_board; y++) {
+ if (wc->modtype[y] != MOD_TYPE_BRI) {
+ if (!(wc->cmdq[y].cmds[x] & __CMD_FIN))
+ wc->cmdq[y].cmds[x] &= ~(__CMD_TX | (0xff << 24));
+ }
}
}
spin_unlock_irqrestore(&wc->reglock, flags);
@@ -1085,8 +1136,8 @@
int i;
register u8 *chanchunk;
- for (i = 0; i < wc->cards; i += 4) {
- chanchunk = &wc->chans[0 + i]->readchunk[0];
+ for (i = 0; i < wc->avchannels; i += 4) {
+ chanchunk = &wc->chans[0 + i]->chan.readchunk[0];
chanchunk[0] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*0];
chanchunk[1] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*1];
chanchunk[2] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*2];
@@ -1096,7 +1147,7 @@
chanchunk[6] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*6];
chanchunk[7] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*7];
- chanchunk = &wc->chans[1 + i]->readchunk[0];
+ chanchunk = &wc->chans[1 + i]->chan.readchunk[0];
chanchunk[0] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*0];
chanchunk[1] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*1];
chanchunk[2] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*2];
@@ -1106,7 +1157,7 @@
chanchunk[6] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*6];
chanchunk[7] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*7];
- chanchunk = &wc->chans[2 + i]->readchunk[0];
+ chanchunk = &wc->chans[2 + i]->chan.readchunk[0];
chanchunk[0] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*0];
chanchunk[1] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*1];
chanchunk[2] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*2];
@@ -1116,7 +1167,7 @@
chanchunk[6] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*6];
chanchunk[7] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*7];
- chanchunk = &wc->chans[3 + i]->readchunk[0];
+ chanchunk = &wc->chans[3 + i]->chan.readchunk[0];
chanchunk[0] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*0];
chanchunk[1] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*1];
chanchunk[2] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*2];
@@ -1128,9 +1179,10 @@
}
}
-static inline void wctdm_receiveprep(struct wctdm *wc, unsigned char *readchunk)
+static inline void wctdm_receiveprep(struct wctdm *wc, const u8 *readchunk)
{
int x,y;
+ bool irqmiss = 0;
unsigned char expected;
if (unlikely(!is_good_frame(readchunk)))
@@ -1139,38 +1191,56 @@
if (likely(wc->initialized))
extract_tdm_data(wc, readchunk);
- for (x=0;x<DAHDI_CHUNKSIZE;x++) {
+ for (x = 0; x < DAHDI_CHUNKSIZE; x++) {
if (x < DAHDI_CHUNKSIZE - 1) {
expected = wc->rxident+1;
wc->rxident = readchunk[EFRAME_SIZE + 1];
if (wc->rxident != expected) {
- wc->span.irqmisses++;
+ irqmiss = 1;
cmd_retransmit(wc);
}
}
- for (y=0;y < wc->cards;y++) {
+ for (y = 0; y < wc->avchannels; y++) {
if (x < 3)
cmd_decipher(wc, readchunk, y);
}
if (wc->vpm100) {
- for (y=NUM_CARDS;y < NUM_CARDS + NUM_EC; y++)
+ for (y = NUM_MODULES; y < NUM_MODULES + NUM_EC; y++)
cmd_decipher(wc, readchunk, y);
- } else if (wc->vpmadt032) {
+ } else if (wc->vpmadt032)
cmd_decipher_vpmadt032(wc, readchunk);
- }
readchunk += (EFRAME_SIZE + EFRAME_GAP);
}
+
/* XXX We're wasting 8 taps. We should get closer :( */
if (likely(wc->initialized)) {
- for (x = 0; x < wc->desc->ports; x++) {
- if (wc->cardflag & (1 << x))
- dahdi_ec_chunk(wc->chans[x], wc->chans[x]->readchunk, wc->chans[x]->writechunk);
- }
- dahdi_receive(&wc->span);
- }
+ for (x = 0; x < wc->avchannels; x++) {
+ struct dahdi_chan *c = &wc->chans[x]->chan;
+ dahdi_ec_chunk(c, c->readchunk, c->writechunk);
+ }
+
+ for (x = 0; x < MAX_SPANS; x++) {
+ if (wc->spans[x]) {
+ struct dahdi_span *s = &wc->spans[x]->span;
+#if 1
+ /* Check for digital spans */
+ if (s->chanconfig == b400m_chanconfig) {
+ BUG_ON(!is_hx8(wc));
+ if (s->flags & DAHDI_FLAG_RUNNING)
+ b400m_dchan(s);
+
+ }
+#endif
+ dahdi_receive(s);
+ if (unlikely(irqmiss))
+ ++s->irqmisses;
+ }
+ }
+ }
+
/* Wake up anyone sleeping to read/write a new register */
- wake_up_interruptible(&wc->regq);
+ wake_up_interruptible_all(&wc->regq);
}
static int wait_access(struct wctdm *wc, int card)
@@ -1193,7 +1263,8 @@
}
- if(count > (MAX-1)) dev_notice(&wc->vb.pdev->dev, " ##### Loop error (%02x) #####\n", data);
+ if (count > (MAX-1))
[... 5425 lines stripped ...]
More information about the dahdi-commits
mailing list