wcb4xxp: Add support for wcb23x series
Adds support for Digium's new dual span wcb23x series cards. Also other minor improvements for the new generation cards including the wcb23x and wcb43x Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
This commit is contained in:
parent
dd3c4ba015
commit
80e0426dd6
@ -110,7 +110,7 @@ static int led_fader_table[] = {
|
||||
20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0,
|
||||
};
|
||||
|
||||
// #define CREATE_WCB4XXP_PROCFS_ENTRY
|
||||
#undef CREATE_WCB4XXP_PROCFS_ENTRY
|
||||
#ifdef CREATE_WCB4XXP_PROCFS_ENTRY
|
||||
#define PROCFS_NAME "wcb4xxp"
|
||||
static struct proc_dir_entry *myproc;
|
||||
@ -132,6 +132,8 @@ static struct devtype wcb41xp = {"Wildcard B410P", .ports = 4,
|
||||
.card_type = B410P};
|
||||
static struct devtype wcb43xp = {"Wildcard B430P", .ports = 4,
|
||||
.card_type = B430P};
|
||||
static struct devtype wcb23xp = {"Wildcard B230P", .ports = 2,
|
||||
.card_type = B230P};
|
||||
static struct devtype hfc2s = {"HFC-2S Junghanns.NET duoBRI PCI", .ports = 2, .card_type = DUOBRI };
|
||||
static struct devtype hfc4s = {"HFC-4S Junghanns.NET quadBRI PCI", .ports = 4, .card_type = QUADBRI };
|
||||
static struct devtype hfc8s = {"HFC-8S Junghanns.NET octoBRI PCI", .ports = 8, .card_type = OCTOBRI };
|
||||
@ -146,8 +148,10 @@ static struct devtype hfc4s_EV = {"CCD HFC-4S Eval. Board", .ports = 4,
|
||||
.card_type = QUADBRI_EVAL };
|
||||
|
||||
#define IS_B430P(card) ((card)->card_type == B430P)
|
||||
#define IS_B230P(card) ((card)->card_type == B230P)
|
||||
#define IS_GEN2(card) (IS_B430P(card) || IS_B230P(card))
|
||||
#define IS_B410P(card) ((card)->card_type == B410P)
|
||||
#define CARD_HAS_EC(card) (IS_B410P(card) || IS_B430P(card))
|
||||
#define CARD_HAS_EC(card) (IS_B410P(card) || IS_B430P(card) || IS_B230P(card))
|
||||
|
||||
static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
|
||||
static void b4xxp_update_leds(struct b4xxp *b4);
|
||||
@ -415,7 +419,7 @@ static unsigned char b4xxp_getreg_ra(struct b4xxp *b4, unsigned char r, unsigned
|
||||
* cleared, as it's used for reset */
|
||||
static void hfc_gpio_set(struct b4xxp *b4, unsigned char bits)
|
||||
{
|
||||
if (IS_B430P(b4)) {
|
||||
if (IS_GEN2(b4)) {
|
||||
b4xxp_setreg8(b4, R_GPIO_OUT1, bits | 0x01);
|
||||
flush_pci();
|
||||
} else {
|
||||
@ -449,7 +453,7 @@ static void hfc_gpio_init(struct b4xxp *b4)
|
||||
/* GPIO0..7 input */
|
||||
b4xxp_setreg8(b4, R_GPIO_EN0, 0x00);
|
||||
|
||||
if (IS_B430P(b4))
|
||||
if (IS_GEN2(b4))
|
||||
b4xxp_setreg8(b4, R_GPIO_EN1, 0xf1);
|
||||
else
|
||||
b4xxp_setreg8(b4, R_GPIO_EN1, 0xf7);
|
||||
@ -835,7 +839,7 @@ static void ec_init(struct b4xxp *b4)
|
||||
return;
|
||||
|
||||
/* Short circuit to the new zarlink echocan logic */
|
||||
if (IS_B430P(b4)) {
|
||||
if (IS_GEN2(b4)) {
|
||||
zl_init(b4);
|
||||
return;
|
||||
}
|
||||
@ -1030,7 +1034,7 @@ static void hfc_reset(struct b4xxp *b4)
|
||||
b4xxp_setreg8(b4, R_PCM_MD0, V_PCM_MD | V_PCM_IDX_MD1);
|
||||
flush_pci();
|
||||
|
||||
if (IS_B430P(b4))
|
||||
if (IS_GEN2(b4))
|
||||
b4xxp_setreg8(b4, R_PCM_MD1, V_PLL_ADJ_00 | V_PCM_DR_4096);
|
||||
else
|
||||
b4xxp_setreg8(b4, R_PCM_MD1, V_PLL_ADJ_00 | V_PCM_DR_2048);
|
||||
@ -1195,6 +1199,9 @@ static void hfc_assign_fifo_zl(struct b4xxp *b4, int port, int bchan)
|
||||
}
|
||||
|
||||
/* record the host's FIFO # in the span fifo array */
|
||||
if (IS_B230P(b4))
|
||||
b4->spans[2-port].fifos[bchan] = fifo;
|
||||
else
|
||||
b4->spans[3-port].fifos[bchan] = fifo;
|
||||
spin_lock_irqsave(&b4->fifolock, irq_flags);
|
||||
|
||||
@ -1348,6 +1355,8 @@ static void hfc_assign_dchan_fifo(struct b4xxp *b4, int port)
|
||||
/* record the host's FIFO # in the span fifo array */
|
||||
if (IS_B430P(b4))
|
||||
b4->spans[3-port].fifos[2] = fifo;
|
||||
else if (IS_B230P(b4))
|
||||
b4->spans[2-port].fifos[2] = fifo;
|
||||
else
|
||||
b4->spans[port].fifos[2] = fifo;
|
||||
|
||||
@ -1409,11 +1418,15 @@ static void hfc_reset_fifo_pair(struct b4xxp *b4, int fifo, int reset, int force
|
||||
static void b4xxp_set_sync_src(struct b4xxp *b4, int port)
|
||||
{
|
||||
int b;
|
||||
struct b4xxp_span *bspan;
|
||||
|
||||
if (port == -1) /* automatic */
|
||||
/* -1 = no timing selection */
|
||||
if (port == -1) {
|
||||
b = 0;
|
||||
else
|
||||
b = (port & V_SYNC_SEL_MASK) | V_MAN_SYNC;
|
||||
} else {
|
||||
bspan = &b4->spans[port];
|
||||
b = (bspan->phy_port & V_SYNC_SEL_MASK) | V_MAN_SYNC;
|
||||
}
|
||||
|
||||
b4xxp_setreg8(b4, R_ST_SYNC, b);
|
||||
b4->syncspan = port;
|
||||
@ -1481,7 +1494,7 @@ static void remove_sysfs_files(struct b4xxp *b4)
|
||||
* Performs no hardware access whatsoever, but does use GFP_KERNEL so do not call from IRQ context.
|
||||
* if full == 1, prints a "full" dump; otherwise just prints current state.
|
||||
*/
|
||||
static char *hfc_decode_st_state(struct b4xxp *b4, int port, unsigned char state, int full)
|
||||
static char *hfc_decode_st_state(struct b4xxp *b4, struct b4xxp_span *span, unsigned char state, int full)
|
||||
{
|
||||
int nt, sta;
|
||||
char s[128], *str;
|
||||
@ -1498,10 +1511,10 @@ static char *hfc_decode_st_state(struct b4xxp *b4, int port, unsigned char state
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nt = (b4->spans[port].te_mode == 0);
|
||||
nt = !span->te_mode;
|
||||
sta = (state & V_ST_STA_MASK);
|
||||
|
||||
sprintf(str, "P%d: %s state %c%d (%s)", port + 1, (nt ? "NT" : "TE"), (nt ? 'G' : 'F'), sta, ststr[nt][sta]);
|
||||
sprintf(str, "P%d: %s state %c%d (%s)", span->port + 1, (nt ? "NT" : "TE"), (nt ? 'G' : 'F'), sta, ststr[nt][sta]);
|
||||
|
||||
if (full) {
|
||||
sprintf(s, " SYNC: %s, RX INFO0: %s", ((state & V_FR_SYNC) ? "yes" : "no"), ((state & V_INFO0) ? "yes" : "no"));
|
||||
@ -1522,28 +1535,29 @@ static char *hfc_decode_st_state(struct b4xxp *b4, int port, unsigned char state
|
||||
* if 'auto' is nonzero, will put the state machine back in auto mode after setting the state.
|
||||
*/
|
||||
static void hfc_handle_state(struct b4xxp_span *s);
|
||||
static void hfc_force_st_state(struct b4xxp *b4, int port, int state, int resume_auto)
|
||||
static void hfc_force_st_state(struct b4xxp *b4, struct b4xxp_span *s, int state, int resume_auto)
|
||||
{
|
||||
b4xxp_setreg_ra(b4, R_ST_SEL, port, A_ST_RD_STA, state | V_ST_LD_STA);
|
||||
b4xxp_setreg_ra(b4, R_ST_SEL, s->phy_port,
|
||||
A_ST_RD_STA, state | V_ST_LD_STA);
|
||||
|
||||
udelay(6);
|
||||
|
||||
if (resume_auto) {
|
||||
b4xxp_setreg_ra(b4, R_ST_SEL, port, A_ST_RD_STA, state);
|
||||
b4xxp_setreg_ra(b4, R_ST_SEL, s->phy_port, A_ST_RD_STA, state);
|
||||
}
|
||||
|
||||
if (DBG_ST) {
|
||||
char *x;
|
||||
|
||||
x = hfc_decode_st_state(b4, port, state, 1);
|
||||
x = hfc_decode_st_state(b4, s, state, 1);
|
||||
dev_info(&b4->pdev->dev,
|
||||
"forced port %d to state %d (auto: %d), "
|
||||
"new decode: %s\n", port + 1, state, resume_auto, x);
|
||||
"forced port %d to state %d (auto: %d), new decode: %s\n",
|
||||
s->port + 1, state, resume_auto, x);
|
||||
kfree(x);
|
||||
}
|
||||
|
||||
/* make sure that we activate any timers/etc needed by this state change */
|
||||
hfc_handle_state(&b4->spans[port]);
|
||||
hfc_handle_state(s);
|
||||
}
|
||||
|
||||
static void hfc_stop_st(struct b4xxp_span *s);
|
||||
@ -1578,10 +1592,10 @@ static void hfc_timer_expire(struct b4xxp_span *s, int t_no)
|
||||
|
||||
switch(t_no) {
|
||||
case HFC_T1: /* switch to G4 (pending deact.), resume auto mode */
|
||||
hfc_force_st_state(b4, s->phy_port, 4, 1);
|
||||
hfc_force_st_state(b4, s, 4, 1);
|
||||
break;
|
||||
case HFC_T2: /* switch to G1 (deactivated), resume auto mode */
|
||||
hfc_force_st_state(b4, s->phy_port, 1, 1);
|
||||
hfc_force_st_state(b4, s, 1, 1);
|
||||
break;
|
||||
case HFC_T3: /* switch to F3 (deactivated), resume auto mode */
|
||||
hfc_stop_st(s);
|
||||
@ -1659,7 +1673,7 @@ static void hfc_handle_state(struct b4xxp_span *s)
|
||||
if (DBG_ST) {
|
||||
char *x;
|
||||
|
||||
x = hfc_decode_st_state(b4, s->phy_port, state, 1);
|
||||
x = hfc_decode_st_state(b4, s, state, 1);
|
||||
dev_info(&b4->pdev->dev,
|
||||
"port %d phy_port %d A_ST_RD_STA old=0x%02x now=0x%02x, decoded: %s\n",
|
||||
s->port + 1, s->phy_port, s->oldstate, state, x);
|
||||
@ -1846,7 +1860,7 @@ static void hfc_init_all_st(struct b4xxp *b4)
|
||||
struct b4xxp_span *s;
|
||||
|
||||
/* All other cards supported by this driver read jumpers for modes */
|
||||
if (!IS_B430P(b4))
|
||||
if (!IS_GEN2(b4))
|
||||
gpio = b4xxp_getreg8(b4, R_GPI_IN3);
|
||||
|
||||
for (i=0; i < b4->numspans; i++) {
|
||||
@ -1858,6 +1872,11 @@ static void hfc_init_all_st(struct b4xxp *b4)
|
||||
/* Port 0-3 in b4->spans[] are physically ports 3-0 */
|
||||
s->phy_port = b4->numspans-1-i;
|
||||
s->port = i;
|
||||
} else if (IS_B230P(b4)) {
|
||||
/* The physical ports are reversed on the b230 */
|
||||
/* Port 0-1 in b4->spans[] are physically ports 2-1 */
|
||||
s->phy_port = b4->numspans - i;
|
||||
s->port = i;
|
||||
} else {
|
||||
s->phy_port = i;
|
||||
s->port = i;
|
||||
@ -1870,8 +1889,8 @@ static void hfc_init_all_st(struct b4xxp *b4)
|
||||
*/
|
||||
if (IS_B410P(b4)) {
|
||||
nt = ((gpio & (1 << (i + 4))) == 0);
|
||||
} else if (IS_B430P(b4)) {
|
||||
/* Read default digital lineconfig reg on B430 */
|
||||
} else if (IS_GEN2(b4)) {
|
||||
/* Read default digital lineconfig reg on GEN2 */
|
||||
int reg;
|
||||
unsigned long flags;
|
||||
|
||||
@ -2257,7 +2276,7 @@ static void b4xxp_init_stage1(struct b4xxp *b4)
|
||||
* incoming clock.
|
||||
*/
|
||||
|
||||
if (IS_B410P(b4) || IS_B430P(b4) || (b4->card_type == QUADBRI_EVAL))
|
||||
if (IS_B410P(b4) || IS_GEN2(b4) || (b4->card_type == QUADBRI_EVAL))
|
||||
b4xxp_setreg8(b4, R_BRG_PCM_CFG, 0x02);
|
||||
else
|
||||
b4xxp_setreg8(b4, R_BRG_PCM_CFG, V_PCM_CLK);
|
||||
@ -2293,7 +2312,7 @@ static void b4xxp_init_stage2(struct b4xxp *b4)
|
||||
b4xxp_setreg8(b4, R_PCM_MD0, V_PCM_MD | V_PCM_IDX_MD1);
|
||||
flush_pci();
|
||||
|
||||
if (IS_B430P(b4)) {
|
||||
if (IS_GEN2(b4)) {
|
||||
b4xxp_setreg8(b4, R_PCM_MD1, V_PLL_ADJ_00 | V_PCM_DR_4096);
|
||||
b4xxp_setreg8(b4, R_PWM_MD, 0x50);
|
||||
b4xxp_setreg8(b4, R_PWM0, 0x38);
|
||||
@ -2352,6 +2371,10 @@ static void b4xxp_init_stage2(struct b4xxp *b4)
|
||||
hfc_assign_fifo_zl(b4, span, 0);
|
||||
hfc_assign_fifo_zl(b4, span, 1);
|
||||
hfc_assign_dchan_fifo(b4, span);
|
||||
} else if (IS_B230P(b4)) {
|
||||
hfc_assign_fifo_zl(b4, span + 1, 0);
|
||||
hfc_assign_fifo_zl(b4, span + 1, 1);
|
||||
hfc_assign_dchan_fifo(b4, span + 1);
|
||||
} else {
|
||||
if ((vpmsupport) && (CARD_HAS_EC(b4))) {
|
||||
hfc_assign_bchan_fifo_ec(b4, span, 0);
|
||||
@ -2454,11 +2477,16 @@ static void b4xxp_update_leds_hfc(struct b4xxp *b4)
|
||||
|
||||
static void b4xxp_set_span_led(struct b4xxp *b4, int span, unsigned char val)
|
||||
{
|
||||
if (IS_B430P(b4)) {
|
||||
if (IS_GEN2(b4)) {
|
||||
unsigned long flags;
|
||||
|
||||
if (IS_B230P(b4)) {
|
||||
b4->ledreg &= ~(0x03 << (span + 1)*2);
|
||||
b4->ledreg |= (val << (span + 1)*2);
|
||||
} else {
|
||||
b4->ledreg &= ~(0x03 << span*2);
|
||||
b4->ledreg |= (val << span*2);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&b4->seqlock, flags);
|
||||
/* Set multiplexer for led R/W */
|
||||
@ -2488,7 +2516,7 @@ static void b4xxp_update_leds(struct b4xxp *b4)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IS_B410P(b4) && !IS_B430P(b4)) {
|
||||
if (!IS_B410P(b4) && !IS_GEN2(b4)) {
|
||||
/* Use the alternative function for non-Digium HFC-4S cards */
|
||||
b4xxp_update_leds_hfc(b4);
|
||||
return;
|
||||
@ -2535,7 +2563,7 @@ static const char *b4xxp_echocan_name(const struct dahdi_chan *chan)
|
||||
if (IS_B410P(bspan->parent))
|
||||
return "LASVEGAS2";
|
||||
|
||||
if (IS_B430P(bspan->parent))
|
||||
if (IS_GEN2(bspan->parent))
|
||||
return "ZARLINK";
|
||||
|
||||
return NULL;
|
||||
@ -2569,22 +2597,23 @@ static int b4xxp_echocan_create(struct dahdi_chan *chan,
|
||||
if (DBG_EC)
|
||||
printk("Enabling echo cancellation on chan %d span %d\n", chan->chanpos, chan->span->offset);
|
||||
|
||||
channel = (chan->span->offset * 8) + ((chan->chanpos - 1) * 4) + 1;
|
||||
|
||||
if (IS_B430P(bspan->parent)) {
|
||||
/* Zarlink has 4 groups of 2 channel echo cancelers */
|
||||
/* Each channel has it's own individual control reg */
|
||||
int group = (3 - chan->span->offset) * 0x40;
|
||||
if (IS_GEN2(bspan->parent)) {
|
||||
int group;
|
||||
int chan_offset = (chan->chanpos % 2) ? 0x00 : 0x20;
|
||||
int reg;
|
||||
unsigned long flags;
|
||||
|
||||
/* Zarlink has 4 groups of 2 channel echo cancelers */
|
||||
/* Each channel has it's own individual control reg */
|
||||
group = bspan->phy_port * 0x40;
|
||||
|
||||
spin_lock_irqsave(&bspan->parent->seqlock, flags);
|
||||
reg = __zl_read(bspan->parent, group + chan_offset);
|
||||
reg &= ~(1 << 3);
|
||||
__zl_write(bspan->parent, group + chan_offset, reg);
|
||||
spin_unlock_irqrestore(&bspan->parent->seqlock, flags);
|
||||
} else {
|
||||
channel = (chan->span->offset * 8) + ((chan->chanpos - 1) * 4) + 1;
|
||||
ec_write(bspan->parent, chan->chanpos - 1, channel, 0x7e);
|
||||
}
|
||||
|
||||
@ -2601,22 +2630,23 @@ static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec
|
||||
if (DBG_EC)
|
||||
printk("Disabling echo cancellation on chan %d span %d\n", chan->chanpos, chan->span->offset);
|
||||
|
||||
channel = (chan->span->offset * 8) + ((chan->chanpos - 1) * 4) + 1;
|
||||
|
||||
if (IS_B430P(bspan->parent)) {
|
||||
/* Zarlink has 4 groups of 2 channel echo cancelers */
|
||||
/* Each channel has it's own individual control reg */
|
||||
int group = (3 - chan->span->offset) * 0x40;
|
||||
if (IS_GEN2(bspan->parent)) {
|
||||
int group;
|
||||
int chan_offset = (chan->chanpos % 2) ? 0x00 : 0x20;
|
||||
int reg;
|
||||
unsigned long flags;
|
||||
|
||||
/* Zarlink has 4 groups of 2 channel echo cancelers */
|
||||
/* Each channel has it's own individual control reg */
|
||||
group = bspan->phy_port * 0x40;
|
||||
|
||||
spin_lock_irqsave(&bspan->parent->seqlock, flags);
|
||||
reg = __zl_read(bspan->parent, group + chan_offset);
|
||||
reg |= (1 << 3);
|
||||
__zl_write(bspan->parent, group + chan_offset, reg);
|
||||
spin_unlock_irqrestore(&bspan->parent->seqlock, flags);
|
||||
} else {
|
||||
channel = (chan->span->offset * 8) + ((chan->chanpos - 1) * 4) + 1;
|
||||
ec_write(bspan->parent, chan->chanpos - 1, channel, 0x01);
|
||||
}
|
||||
}
|
||||
@ -2677,7 +2707,7 @@ static int b4xxp_spanconfig(struct file *file, struct dahdi_span *span,
|
||||
if (DBG)
|
||||
dev_info(&b4->pdev->dev, "Configuring span %d offset %d to be sync %d\n", span->spanno, span->offset, lc->sync);
|
||||
|
||||
if (lc->sync < 0 || lc->sync > 4) {
|
||||
if (lc->sync < 0 || lc->sync > b4->numspans) {
|
||||
dev_info(&b4->pdev->dev,
|
||||
"Span %d has invalid sync priority (%d), removing "
|
||||
"from sync source list\n", span->spanno, lc->sync);
|
||||
@ -2695,7 +2725,7 @@ static int b4xxp_spanconfig(struct file *file, struct dahdi_span *span,
|
||||
b4->spans[lc->sync - 1].sync = (span->offset + 1);
|
||||
|
||||
/* B430 sets TE/NT and Termination resistance modes via dahdi_cfg */
|
||||
if (IS_B430P(b4)) {
|
||||
if (IS_GEN2(b4)) {
|
||||
int te_mode, term, reg;
|
||||
unsigned long flags;
|
||||
|
||||
@ -2718,22 +2748,24 @@ static int b4xxp_spanconfig(struct file *file, struct dahdi_span *span,
|
||||
spin_lock_irqsave(&b4->seqlock, flags);
|
||||
hfc_gpio_set(b4, 0x20);
|
||||
reg = hfc_sram_read(b4);
|
||||
hfc_gpio_set(b4, 0x00);
|
||||
|
||||
if (te_mode)
|
||||
reg &= ~(1 << (4 + bspan->port));
|
||||
reg &= ~(1 << (7 - bspan->phy_port));
|
||||
else
|
||||
reg |= (1 << (4 + bspan->port));
|
||||
reg |= (1 << (7 - bspan->phy_port));
|
||||
|
||||
/* Setup Termination resistance */
|
||||
/* Bits 4 downto 0 correspond to spans 4-1 */
|
||||
/* 1 sets resistance mode, 0 sets no resistance */
|
||||
if (term)
|
||||
reg |= (1 << (bspan->port));
|
||||
reg |= (1 << (3 - bspan->phy_port));
|
||||
else
|
||||
reg &= ~(1 << (bspan->port));
|
||||
reg &= ~(1 << (3 - bspan->phy_port));
|
||||
|
||||
hfc_gpio_set(b4, 0x20);
|
||||
hfc_sram_write(b4, reg);
|
||||
hfc_gpio_set(b4, 0x00);
|
||||
spin_unlock_irqrestore(&b4->seqlock, flags);
|
||||
|
||||
bspan->te_mode = te_mode;
|
||||
@ -3026,6 +3058,40 @@ static void b4xxp_bottom_half(unsigned long data)
|
||||
if (b4->shutdown)
|
||||
return;
|
||||
|
||||
if (IS_GEN2(b4)) {
|
||||
unsigned long timeout = jiffies + (HZ/10);
|
||||
int i;
|
||||
struct b4xxp_span *bspan;
|
||||
|
||||
for (i = 0; i < b4->numspans; i++) {
|
||||
/* Map the ports from the virtual ports to the fifos */
|
||||
bspan = &b4->spans[i];
|
||||
b = (b4->fifo_irqstatus[2] >> (2 * bspan->phy_port));
|
||||
|
||||
if (b & V_IRQ_FIFOx_TX) {
|
||||
while (hdlc_tx_frame(&b4->spans[i])) {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
dev_err(&b4->pdev->dev,
|
||||
"bottom_half timed out\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (b & V_IRQ_FIFOx_RX) {
|
||||
while (hdlc_rx_frame(&b4->spans[i])) {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
dev_err(&b4->pdev->dev,
|
||||
"bottom_half timed out\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b4->fifo_irqstatus[2] = 0;
|
||||
} else {
|
||||
|
||||
/* HFC-4S d-chan fifos 8-11 *** HFC-8S d-chan fifos 16-23 */
|
||||
if (b4->numspans == 8) {
|
||||
fifo_low = 16;
|
||||
@ -3052,9 +3118,6 @@ static void b4xxp_bottom_half(unsigned long data)
|
||||
* Yuck. It works well, but yuck.
|
||||
*/
|
||||
do {
|
||||
if (IS_B430P(b4))
|
||||
k = hdlc_tx_frame(&b4->spans[3-(fifo - fifo_low)]);
|
||||
else
|
||||
k = hdlc_tx_frame(&b4->spans[fifo - fifo_low]);
|
||||
} while (k);
|
||||
} else {
|
||||
@ -3072,9 +3135,6 @@ static void b4xxp_bottom_half(unsigned long data)
|
||||
* i.e. I get an int when F1 changes, not when F1 != F2.
|
||||
*/
|
||||
do {
|
||||
if (IS_B430P(b4))
|
||||
k = hdlc_rx_frame(&b4->spans[3-(fifo - fifo_low)]);
|
||||
else
|
||||
k = hdlc_rx_frame(&b4->spans[fifo - fifo_low]);
|
||||
} while (k);
|
||||
} else {
|
||||
@ -3089,6 +3149,7 @@ static void b4xxp_bottom_half(unsigned long data)
|
||||
/* zero the bits we just processed */
|
||||
b4->fifo_irqstatus[i] &= ~b2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* timer interrupt
|
||||
@ -3112,6 +3173,10 @@ static void b4xxp_bottom_half(unsigned long data)
|
||||
b = b4xxp_getreg8(b4, R_SCI);
|
||||
if (b) {
|
||||
for (i=0; i < b4->numspans; i++) {
|
||||
if (IS_B230P(b4)) {
|
||||
if (b & (1 << (i+1)))
|
||||
hfc_handle_state(&b4->spans[1-i]);
|
||||
} else {
|
||||
if (b & (1 << i)) {
|
||||
/* physical spans are reversed for b430 */
|
||||
if (IS_B430P(b4))
|
||||
@ -3122,6 +3187,7 @@ static void b4xxp_bottom_half(unsigned long data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We're supposed to kick DAHDI here, too, but again, seeing too much latency between the interrupt and the bottom-half. */
|
||||
|
||||
@ -3189,7 +3255,7 @@ static int b4xxp_proc_read_one(char *buf, struct b4xxp *b4)
|
||||
struct b4xxp_span *s = &b4->spans[i];
|
||||
|
||||
state = b4xxp_getreg_ra(b4, R_ST_SEL, s->port, A_ST_RD_STA);
|
||||
x = hfc_decode_st_state(b4, s->port, state, 0);
|
||||
x = hfc_decode_st_state(b4, s, state, 0);
|
||||
sprintf(str, "%s\n", x);
|
||||
strcat(sBuf, str);
|
||||
kfree(x);
|
||||
@ -3338,7 +3404,7 @@ static int __devinit b4xx_probe(struct pci_dev *pdev, const struct pci_device_id
|
||||
|
||||
b4xxp_init_stage1(b4);
|
||||
|
||||
if (IS_B430P(b4)) {
|
||||
if (IS_GEN2(b4)) {
|
||||
int version;
|
||||
unsigned long flags;
|
||||
|
||||
@ -3472,6 +3538,8 @@ static DEFINE_PCI_DEVICE_TABLE(b4xx_ids) =
|
||||
{0xd161, 0xb410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb41xp},
|
||||
{0xd161, 0x8014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb43xp},
|
||||
{0xd161, 0x8015, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb43xp},
|
||||
{0xd161, 0x8016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb23xp},
|
||||
{0xd161, 0x8017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb23xp},
|
||||
{0x1397, 0x16b8, 0x1397, 0xb552, 0, 0, (unsigned long)&hfc8s},
|
||||
{0x1397, 0x16b8, 0x1397, 0xb55b, 0, 0, (unsigned long)&hfc8s},
|
||||
{0x1397, 0x08b4, 0x1397, 0xb520, 0, 0, (unsigned long)&hfc4s},
|
||||
|
@ -428,7 +428,8 @@ enum cards_ids { /* Cards ==> Brand & Model */
|
||||
BN8S0, /* BeroNet BN8S0 */
|
||||
BSWYX_SX2, /* Swyx 4xS0 SX2 QuadBri */
|
||||
QUADBRI_EVAL, /* HFC-4S CCD Eval. Board */
|
||||
B430P /* Digium B430P */
|
||||
B430P, /* Digium B430P */
|
||||
B230P /* Digium B230P */
|
||||
};
|
||||
|
||||
/* This structure exists one per card */
|
||||
|
Loading…
Reference in New Issue
Block a user