common channel_t for w6692

handle SHORTSTATUS for isac
This commit is contained in:
Karsten Keil 2005-12-11 18:27:08 +00:00
parent ab7fd00493
commit 32dd9af3eb
2 changed files with 221 additions and 208 deletions

View File

@ -668,7 +668,9 @@ mISDN_ISAC_l1hw(mISDNinstance_t *inst, struct sk_buff *skb)
} }
#endif #endif
ret = 0; ret = 0;
} else { } else if ((hh->prim & MISDN_CMD_MASK) == MGR_SHORTSTATUS)
ret = -EAGAIN;
else {
if (dch->debug & L1_DEB_WARN) if (dch->debug & L1_DEB_WARN)
mISDN_debugprint(&dch->inst, "isac_l1hw unknown prim %x", mISDN_debugprint(&dch->inst, "isac_l1hw unknown prim %x",
hh->prim); hh->prim);

View File

@ -27,7 +27,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include "channel.h" #include "channel.h"
#include "bchannel.h"
#include "layer1.h" #include "layer1.h"
#include "helper.h" #include "helper.h"
#include "debug.h" #include "debug.h"
@ -61,7 +60,7 @@ typedef struct _w6692pci {
u_char xdata; u_char xdata;
w6692_bc wbc[2]; w6692_bc wbc[2];
channel_t dch; channel_t dch;
bchannel_t bch[2]; channel_t bch[2];
} w6692pci; } w6692pci;
#define W_LED1_ON 1 #define W_LED1_ON 1
@ -152,10 +151,12 @@ W6692_new_ph(channel_t *dch)
case W_L1IND_CD: case W_L1IND_CD:
prim = PH_CONTROL | CONFIRM; prim = PH_CONTROL | CONFIRM;
para = HW_DEACTIVATE; para = HW_DEACTIVATE;
test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
break; break;
case W_L1IND_DRD: case W_L1IND_DRD:
prim = PH_CONTROL | INDICATION; prim = PH_CONTROL | INDICATION;
para = HW_DEACTIVATE; para = HW_DEACTIVATE;
test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
break; break;
case W_L1IND_CE: case W_L1IND_CE:
prim = PH_CONTROL | INDICATION; prim = PH_CONTROL | INDICATION;
@ -169,9 +170,11 @@ W6692_new_ph(channel_t *dch)
break; break;
case W_L1IND_AI8: case W_L1IND_AI8:
para = INFO4_P8; para = INFO4_P8;
test_and_set_bit(FLG_ACTIVE, &dch->Flags);
break; break;
case W_L1IND_AI10: case W_L1IND_AI10:
para = INFO4_P10; para = INFO4_P10;
test_and_set_bit(FLG_ACTIVE, &dch->Flags);
break; break;
default: default:
return; return;
@ -189,13 +192,13 @@ W6692_empty_Dfifo(w6692pci *card, int count)
mISDN_debugprint(&dch->inst, "empty_Dfifo"); mISDN_debugprint(&dch->inst, "empty_Dfifo");
if (!dch->rx_skb) { if (!dch->rx_skb) {
if (!(dch->rx_skb = alloc_stack_skb(MAX_DFRAME_LEN_L1, dch->up_headerlen))) { if (!(dch->rx_skb = alloc_stack_skb(dch->maxlen, dch->up_headerlen))) {
printk(KERN_WARNING "mISDN: D receive out of memory\n"); printk(KERN_WARNING "mISDN: D receive out of memory\n");
WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK); WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);
return; return;
} }
} }
if ((dch->rx_skb->len + count) >= MAX_DFRAME_LEN_L1) { if ((dch->rx_skb->len + count) >= dch->maxlen) {
if (dch->debug & L1_DEB_WARN) if (dch->debug & L1_DEB_WARN)
mISDN_debugprint(&dch->inst, "empty_Dfifo overrun %d", mISDN_debugprint(&dch->inst, "empty_Dfifo overrun %d",
dch->rx_skb->len + count); dch->rx_skb->len + count);
@ -376,7 +379,8 @@ handle_txD(w6692pci *card) {
} }
static void static void
handle_statusD(w6692pci *card) { handle_statusD(w6692pci *card)
{
register channel_t *dch = &card->dch; register channel_t *dch = &card->dch;
u_char exval, v1, cir; u_char exval, v1, cir;
@ -447,43 +451,51 @@ handle_statusD(w6692pci *card) {
} }
static void static void
W6692_empty_Bfifo(bchannel_t *bch, int count) W6692_empty_Bfifo(channel_t *bch, int count)
{ {
u_char *ptr; u_char *ptr;
w6692pci *card = bch->inst.privat; w6692pci *card = bch->inst.privat;
if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO)) if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
mISDN_debugprint(&bch->inst, "empty_Bfifo %d", count); mISDN_debugprint(&bch->inst, "empty_Bfifo %d", count);
if (bch->protocol == ISDN_PID_NONE) { if (unlikely(bch->state == ISDN_PID_NONE)) {
if (bch->debug & L1_DEB_WARN) if (bch->debug & L1_DEB_WARN)
mISDN_debugprint(&bch->inst, "empty_Bfifo ISDN_PID_NONE"); mISDN_debugprint(&bch->inst, "empty_Bfifo ISDN_PID_NONE");
WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
bch->rx_idx = 0; if (bch->rx_skb)
skb_trim(bch->rx_skb, 0);
return; return;
} }
if (bch->rx_idx + count > MAX_DATA_MEM) { if (!bch->rx_skb) {
bch->rx_skb = alloc_stack_skb(bch->maxlen, bch->up_headerlen);
if (unlikely(!bch->rx_skb)) {
printk(KERN_WARNING "mISDN: B receive out of memory\n");
WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
return;
}
}
if (bch->rx_skb->len + count > bch->maxlen) {
if (bch->debug & L1_DEB_WARN) if (bch->debug & L1_DEB_WARN)
mISDN_debugprint(&bch->inst, "empty_Bfifo incoming packet too large"); mISDN_debugprint(&bch->inst, "empty_Bfifo incoming packet too large");
WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
bch->rx_idx = 0; skb_trim(bch->rx_skb, 0);
return; return;
} }
ptr = bch->rx_buf + bch->rx_idx; ptr = skb_put(bch->rx_skb, count);
bch->rx_idx += count;
insb(card->addr + W_B_RFIFO + (bch->channel ? 0x40 : 0), ptr, count); insb(card->addr + W_B_RFIFO + (bch->channel ? 0x40 : 0), ptr, count);
WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
if (bch->debug & L1_DEB_HSCX_FIFO) { if (bch->debug & L1_DEB_HSCX_FIFO) {
char *t = bch->blog; char *t = bch->log;
t += sprintf(t, "empty_Bfifo B%d cnt %d", bch->channel, count); t += sprintf(t, "empty_Bfifo B%d cnt %d", bch->channel, count);
mISDN_QuickHex(t, ptr, count); mISDN_QuickHex(t, ptr, count);
mISDN_debugprint(&bch->inst, bch->blog); mISDN_debugprint(&bch->inst, bch->log);
} }
} }
static void static void
W6692_fill_Bfifo(bchannel_t *bch) W6692_fill_Bfifo(channel_t *bch)
{ {
w6692pci *card = bch->inst.privat; w6692pci *card = bch->inst.privat;
int count; int count;
@ -491,14 +503,16 @@ W6692_fill_Bfifo(bchannel_t *bch)
if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO)) if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
mISDN_debugprint(&bch->inst, "%s", __FUNCTION__); mISDN_debugprint(&bch->inst, "%s", __FUNCTION__);
count = bch->tx_len - bch->tx_idx; if (!bch->tx_skb)
return;
count = bch->tx_skb->len - bch->tx_idx;
if (count <= 0) if (count <= 0)
return; return;
ptr = bch->tx_buf + bch->tx_idx; ptr = bch->tx_skb->data + bch->tx_idx;
if (count > W_B_FIFO_THRESH) { if (count > W_B_FIFO_THRESH) {
count = W_B_FIFO_THRESH; count = W_B_FIFO_THRESH;
} else { } else {
if (bch->protocol != ISDN_PID_L1_B_64TRANS) if (test_bit(FLG_HDLC, &bch->Flags))
cmd |= W_B_CMDR_XME; cmd |= W_B_CMDR_XME;
} }
if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO)) if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
@ -508,23 +522,23 @@ W6692_fill_Bfifo(bchannel_t *bch)
outsb(card->addr + W_B_XFIFO + (bch->channel ? 0x40 : 0), ptr, count); outsb(card->addr + W_B_XFIFO + (bch->channel ? 0x40 : 0), ptr, count);
WriteW6692B(card, bch->channel, W_B_CMDR, cmd); WriteW6692B(card, bch->channel, W_B_CMDR, cmd);
if (bch->debug & L1_DEB_HSCX_FIFO) { if (bch->debug & L1_DEB_HSCX_FIFO) {
char *t = bch->blog; char *t = bch->log;
t += sprintf(t, "fill_Bfifo B%d cnt %d", t += sprintf(t, "fill_Bfifo B%d cnt %d",
bch->channel, count); bch->channel, count);
mISDN_QuickHex(t, ptr, count); mISDN_QuickHex(t, ptr, count);
mISDN_debugprint(&bch->inst, bch->blog); mISDN_debugprint(&bch->inst, bch->log);
} }
} }
static int static int
setvolume(bchannel_t *bch, int mic, struct sk_buff *skb) setvolume(channel_t *bch, int mic, struct sk_buff *skb)
{ {
w6692pci *card = bch->inst.privat; w6692pci *card = bch->inst.privat;
u16 *vol = (u16 *)skb->data; u16 *vol = (u16 *)skb->data;
u_char val; u_char val;
if ((card->pots == 0) || (bch->protocol != ISDN_PID_L1_B_64TRANS)) if ((card->pots == 0) || !test_bit(FLG_TRANSPARENT, &bch->Flags))
return(-ENODEV); return(-ENODEV);
if (skb->len < 2) if (skb->len < 2)
return(-EINVAL); return(-EINVAL);
@ -544,12 +558,12 @@ setvolume(bchannel_t *bch, int mic, struct sk_buff *skb)
} }
static int static int
enable_pots(bchannel_t *bch) enable_pots(channel_t *bch)
{ {
w6692_bc *bhw = bch->hw; w6692_bc *bhw = bch->hw;
w6692pci *card = bch->inst.privat; w6692pci *card = bch->inst.privat;
if ((card->pots == 0) || (bch->protocol != ISDN_PID_L1_B_64TRANS)) if ((card->pots == 0) || !test_bit(FLG_TRANSPARENT, &bch->Flags))
return(-ENODEV); return(-ENODEV);
bhw->b_mode |= W_B_MODE_EPCM | W_B_MODE_BSW0; bhw->b_mode |= W_B_MODE_EPCM | W_B_MODE_BSW0;
@ -561,7 +575,7 @@ enable_pots(bchannel_t *bch)
} }
static int static int
disable_pots(bchannel_t *bch) disable_pots(channel_t *bch)
{ {
w6692_bc *bhw = bch->hw; w6692_bc *bhw = bch->hw;
w6692pci *card = bch->inst.privat; w6692pci *card = bch->inst.privat;
@ -575,7 +589,7 @@ disable_pots(bchannel_t *bch)
} }
static int static int
mode_w6692(bchannel_t *bch, int bc, int protocol) mode_w6692(channel_t *bch, int bc, int protocol)
{ {
w6692pci *card = bch->inst.privat; w6692pci *card = bch->inst.privat;
w6692_bc *bhw = bch->hw; w6692_bc *bhw = bch->hw;
@ -583,43 +597,53 @@ mode_w6692(bchannel_t *bch, int bc, int protocol)
if (bch->debug & L1_DEB_HSCX) if (bch->debug & L1_DEB_HSCX)
mISDN_debugprint(&bch->inst, "B%d protocol %x-->%x ch %d-->%d", mISDN_debugprint(&bch->inst, "B%d protocol %x-->%x ch %d-->%d",
bch->channel, bch->protocol, protocol, bch->channel, bc); bch->channel, bch->state, protocol, bch->channel, bc);
switch (protocol) { switch (protocol) {
case (-1): /* used for init */ case (-1): /* used for init */
bch->protocol = -1; bch->state = -1;
bch->channel = bc; bch->channel = bc;
case (ISDN_PID_NONE): case (ISDN_PID_NONE):
if (bch->protocol == ISDN_PID_NONE) if (bch->state == ISDN_PID_NONE)
break; break;
bch->protocol = ISDN_PID_NONE; bch->state = ISDN_PID_NONE;
if (card->pots && (bhw->b_mode & W_B_MODE_EPCM)) if (card->pots && (bhw->b_mode & W_B_MODE_EPCM))
disable_pots(bch); disable_pots(bch);
bhw->b_mode = 0; bhw->b_mode = 0;
bch->tx_len = 0;
bch->tx_idx = 0; bch->tx_idx = 0;
bch->rx_idx = 0;
if (bch->next_skb) { if (bch->next_skb) {
dev_kfree_skb(bch->next_skb); dev_kfree_skb(bch->next_skb);
bch->next_skb = NULL; bch->next_skb = NULL;
} }
if (bch->tx_skb) {
dev_kfree_skb(bch->tx_skb);
bch->tx_skb = NULL;
}
if (bch->rx_skb) {
dev_kfree_skb(bch->rx_skb);
bch->rx_skb = NULL;
}
WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode); WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode);
WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST); WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
test_and_clear_bit(FLG_HDLC, &bch->Flags);
test_and_clear_bit(FLG_TRANSPARENT, &bch->Flags);
break; break;
case (ISDN_PID_L1_B_64TRANS): case (ISDN_PID_L1_B_64TRANS):
bch->protocol = protocol; bch->state = protocol;
bhw->b_mode = W_B_MODE_MMS; bhw->b_mode = W_B_MODE_MMS;
WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode); WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode);
WriteW6692B(card, bch->channel, W_B_EXIM, 0); WriteW6692B(card, bch->channel, W_B_EXIM, 0);
WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | W_B_CMDR_XRST); WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | W_B_CMDR_XRST);
test_and_set_bit(FLG_TRANSPARENT, &bch->Flags);
break; break;
case (ISDN_PID_L1_B_64HDLC): case (ISDN_PID_L1_B_64HDLC):
bch->protocol = protocol; bch->state = protocol;
bhw->b_mode = W_B_MODE_ITF; bhw->b_mode = W_B_MODE_ITF;
WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode); WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode);
WriteW6692B(card, bch->channel, W_B_ADM1, 0xff); WriteW6692B(card, bch->channel, W_B_ADM1, 0xff);
WriteW6692B(card, bch->channel, W_B_ADM2, 0xff); WriteW6692B(card, bch->channel, W_B_ADM2, 0xff);
WriteW6692B(card, bch->channel, W_B_EXIM, 0); WriteW6692B(card, bch->channel, W_B_EXIM, 0);
WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | W_B_CMDR_XRST); WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | W_B_CMDR_XRST);
test_and_set_bit(FLG_HDLC, &bch->Flags);
break; break;
default: default:
mISDN_debugprint(&bch->inst, "prot not known %x", protocol); mISDN_debugprint(&bch->inst, "prot not known %x", protocol);
@ -629,35 +653,32 @@ mode_w6692(bchannel_t *bch, int bc, int protocol)
} }
static void static void
send_next(bchannel_t *bch) send_next(channel_t *bch)
{ {
if (bch->protocol == ISDN_PID_NONE) if (test_bit(FLG_ACTIVE, &bch->Flags))
return; return;
if (bch->tx_idx < bch->tx_len) if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len)
W6692_fill_Bfifo(bch); W6692_fill_Bfifo(bch);
else { else {
if (bch->tx_skb)
dev_kfree_skb(bch->tx_skb);
bch->tx_idx = 0; bch->tx_idx = 0;
if (test_bit(BC_FLG_TX_NEXT, &bch->Flag)) { if (test_bit(FLG_TX_NEXT, &bch->Flags)) {
struct sk_buff *skb = bch->next_skb; bch->tx_skb = bch->next_skb;
if (skb) { if (bch->tx_skb) {
mISDN_head_t *hh = mISDN_HEAD_P(skb); mISDN_head_t *hh = mISDN_HEAD_P(bch->tx_skb);
bch->next_skb = NULL; bch->next_skb = NULL;
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag); test_and_clear_bit(FLG_TX_NEXT, &bch->Flags);
bch->tx_len = skb->len; queue_ch_frame(bch, CONFIRM, hh->dinfo, NULL);
memcpy(bch->tx_buf, skb->data, bch->tx_len);
W6692_fill_Bfifo(bch); W6692_fill_Bfifo(bch);
skb_trim(skb, 0);
queue_bch_frame(bch, CONFIRM, hh->dinfo, skb);
} else { } else {
bch->tx_len = 0; test_and_clear_bit(FLG_TX_NEXT, &bch->Flags);
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
printk(KERN_WARNING "W6692 tx irq TX_NEXT without skb\n"); printk(KERN_WARNING "W6692 tx irq TX_NEXT without skb\n");
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag); test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
} }
} else { } else {
bch->tx_len = 0; bch->tx_skb = NULL;
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag); test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
} }
} }
} }
@ -665,7 +686,7 @@ send_next(bchannel_t *bch)
static void static void
W6692B_interrupt(w6692pci *card, int ch) W6692B_interrupt(w6692pci *card, int ch)
{ {
bchannel_t *bch = &card->bch[ch]; channel_t *bch = &card->bch[ch];
int count; int count;
u_char stat, star = 0; u_char stat, star = 0;
struct sk_buff *skb; struct sk_buff *skb;
@ -677,46 +698,60 @@ W6692B_interrupt(w6692pci *card, int ch)
if (stat & W_B_EXI_RME) { if (stat & W_B_EXI_RME) {
star = ReadW6692B(card, ch, W_B_STAR); star = ReadW6692B(card, ch, W_B_STAR);
if (star & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) { if (star & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) {
if ((star & W_B_STAR_RDOV) && (bch->protocol != ISDN_PID_NONE)) { if ((star & W_B_STAR_RDOV) && test_bit(FLG_ACTIVE, &bch->Flags)) {
if (bch->debug & L1_DEB_WARN) if (bch->debug & L1_DEB_WARN)
mISDN_debugprint(&bch->inst, "B%d RDOV protocol=%x", mISDN_debugprint(&bch->inst, "B%d RDOV protocol=%x",
ch +1, bch->protocol); ch +1, bch->state);
#ifdef ERROR_STATISTIC #ifdef ERROR_STATISTIC
bch->err_rdo++; bch->err_rdo++;
#endif #endif
} }
if ((star & W_B_STAR_CRCE) && (bch->protocol == ISDN_PID_L1_B_64HDLC)) { if (test_bit(FLG_HDLC, &bch->Flags)) {
if (bch->debug & L1_DEB_WARN) if (star & W_B_STAR_CRCE) {
mISDN_debugprint(&bch->inst, "B%d CRC error", ch +1); if (bch->debug & L1_DEB_WARN)
mISDN_debugprint(&bch->inst,
"B%d CRC error", ch+1);
#ifdef ERROR_STATISTIC #ifdef ERROR_STATISTIC
bch->err_crc++; bch->err_crc++;
#endif #endif
} }
if ((star & W_B_STAR_RMB) && (bch->protocol == ISDN_PID_L1_B_64HDLC)) { if (star & W_B_STAR_RMB) {
if (bch->debug & L1_DEB_WARN) if (bch->debug & L1_DEB_WARN)
mISDN_debugprint(&bch->inst, "B%d message abort", ch +1); mISDN_debugprint(&bch->inst,
"B%d message abort", ch+1);
#ifdef ERROR_STATISTIC #ifdef ERROR_STATISTIC
bch->err_inv++; bch->err_inv++;
#endif #endif
}
} }
WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT); WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
if (bch->rx_skb)
skb_trim(bch->rx_skb, 0);
} else { } else {
count = ReadW6692B(card, ch, W_B_RBCL) & (W_B_FIFO_THRESH - 1); count = ReadW6692B(card, ch, W_B_RBCL) & (W_B_FIFO_THRESH - 1);
if (count == 0) if (count == 0)
count = W_B_FIFO_THRESH; count = W_B_FIFO_THRESH;
W6692_empty_Bfifo(bch, count); W6692_empty_Bfifo(bch, count);
if (bch->rx_idx > 0) { if (bch->rx_skb && bch->rx_skb->len > 0) {
if (bch->debug & L1_DEB_HSCX) if (bch->debug & L1_DEB_HSCX)
mISDN_debugprint(&bch->inst, "Bchan Frame %d", bch->rx_idx); mISDN_debugprint(&bch->inst, "Bchan Frame %d", bch->rx_skb->len);
if (!(skb = alloc_stack_skb(bch->rx_idx, bch->up_headerlen))) if (bch->rx_skb->len < MISDN_COPY_SIZE) {
printk(KERN_WARNING "Bchan receive out of memory\n"); skb = alloc_stack_skb(bch->rx_skb->len, bch->up_headerlen);
else { if (skb) {
memcpy(skb_put(skb, bch->rx_idx), bch->rx_buf, bch->rx_idx); memcpy(skb_put(skb, bch->rx_skb->len),
queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb); bch->rx_skb->data, bch->rx_skb->len);
skb_trim(bch->rx_skb, 0);
} else {
skb = bch->rx_skb;
bch->rx_skb = NULL;
}
} else {
skb = bch->rx_skb;
bch->rx_skb = NULL;
} }
queue_ch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
} }
} }
bch->rx_idx = 0;
} }
if (stat & W_B_EXI_RMR) { if (stat & W_B_EXI_RMR) {
if (!(stat & W_B_EXI_RME)) if (!(stat & W_B_EXI_RME))
@ -724,24 +759,21 @@ W6692B_interrupt(w6692pci *card, int ch)
if (star & W_B_STAR_RDOV) { if (star & W_B_STAR_RDOV) {
if (bch->debug & L1_DEB_WARN) if (bch->debug & L1_DEB_WARN)
mISDN_debugprint(&bch->inst, "B%d RDOV protocol=%x", mISDN_debugprint(&bch->inst, "B%d RDOV protocol=%x",
ch +1, bch->protocol); ch +1, bch->state);
#ifdef ERROR_STATISTIC #ifdef ERROR_STATISTIC
bch->err_rdo++; bch->err_rdo++;
#endif #endif
WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT); WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
} else { } else {
W6692_empty_Bfifo(bch, W_B_FIFO_THRESH); W6692_empty_Bfifo(bch, W_B_FIFO_THRESH);
if ((bch->protocol == ISDN_PID_L1_B_64TRANS) && (bch->rx_idx > 0)) { if (test_bit(FLG_TRANSPARENT, &bch->Flags) &&
bch->rx_skb && (bch->rx_skb->len > 0)) {
/* receive audio data */ /* receive audio data */
if (bch->debug & L1_DEB_HSCX) if (bch->debug & L1_DEB_HSCX)
mISDN_debugprint(&bch->inst, "Bchan Frame %d", bch->rx_idx); mISDN_debugprint(&bch->inst,
if (!(skb = alloc_stack_skb(bch->rx_idx, bch->up_headerlen))) "Bchan Frame %d", bch->rx_skb->len);
printk(KERN_WARNING "Bchan receive out of memory\n"); queue_ch_frame(bch, INDICATION, MISDN_ID_ANY, bch->rx_skb);
else { bch->rx_skb = NULL;
memcpy(skb_put(skb, bch->rx_idx), bch->rx_buf, bch->rx_idx);
queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
}
bch->rx_idx = 0;
} }
} }
} }
@ -749,7 +781,7 @@ W6692B_interrupt(w6692pci *card, int ch)
if (!(star & W_B_STAR_RDOV)) { /* only if it is not handled yet */ if (!(star & W_B_STAR_RDOV)) { /* only if it is not handled yet */
if (bch->debug & L1_DEB_WARN) if (bch->debug & L1_DEB_WARN)
mISDN_debugprint(&bch->inst, "B%d RDOV IRQ protocol=%x", mISDN_debugprint(&bch->inst, "B%d RDOV IRQ protocol=%x",
ch +1, bch->protocol); ch +1, bch->state);
#ifdef ERROR_STATISTIC #ifdef ERROR_STATISTIC
bch->err_rdo++; bch->err_rdo++;
#endif #endif
@ -765,14 +797,14 @@ W6692B_interrupt(w6692pci *card, int ch)
if (star & W_B_STAR_XDOW) { if (star & W_B_STAR_XDOW) {
if (bch->debug & L1_DEB_WARN) if (bch->debug & L1_DEB_WARN)
mISDN_debugprint(&bch->inst, "B%d XDOW protocol=%x", mISDN_debugprint(&bch->inst, "B%d XDOW protocol=%x",
ch +1, bch->protocol); ch +1, bch->state);
#ifdef ERROR_STATISTIC #ifdef ERROR_STATISTIC
bch->err_xdu++; bch->err_xdu++;
#endif #endif
WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT); WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
/* resend */ /* resend */
if (bch->tx_len) { if (bch->tx_skb) {
if (bch->protocol != ISDN_PID_L1_B_64TRANS) if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
bch->tx_idx = 0; bch->tx_idx = 0;
} }
} }
@ -783,14 +815,14 @@ W6692B_interrupt(w6692pci *card, int ch)
if (stat & W_B_EXI_XDUN) { if (stat & W_B_EXI_XDUN) {
if (bch->debug & L1_DEB_WARN) if (bch->debug & L1_DEB_WARN)
mISDN_debugprint(&bch->inst, "B%d XDUN protocol=%x", mISDN_debugprint(&bch->inst, "B%d XDUN protocol=%x",
ch +1, bch->protocol); ch +1, bch->state);
#ifdef ERROR_STATISTIC #ifdef ERROR_STATISTIC
bch->err_xdu++; bch->err_xdu++;
#endif #endif
WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT); WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
/* resend */ /* resend */
if (bch->tx_len) { if (bch->tx_skb) {
if (bch->protocol != ISDN_PID_L1_B_64TRANS) if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
bch->tx_idx = 0; bch->tx_idx = 0;
} }
send_next(bch); send_next(bch);
@ -986,58 +1018,18 @@ MODULE_PARM(layermask, MODULE_PARM_T);
/* Layer2 -> Layer 1 Transfer */ /* Layer2 -> Layer 1 Transfer */
/******************************/ /******************************/
static int static int
w6692_l2l1B(mISDNinstance_t *inst, struct sk_buff *skb) w6692_bmsg(channel_t *bch, struct sk_buff *skb)
{ {
bchannel_t *bch = container_of(inst, bchannel_t, inst);
int ret = 0; int ret = 0;
mISDN_head_t *hh = mISDN_HEAD_P(skb); mISDN_head_t *hh = mISDN_HEAD_P(skb);
u_long flags; u_long flags;
if ((hh->prim == PH_DATA_REQ) if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
|| (hh->prim == (DL_DATA | REQUEST))) {
if (skb->len <= 0) {
printk(KERN_WARNING "%s: skb too small\n", __FUNCTION__);
return(-EINVAL);
}
if (skb->len > MAX_DATA_MEM) {
printk(KERN_WARNING "%s: skb too large\n", __FUNCTION__);
return(-EINVAL);
}
/* check for pending next_skb */
spin_lock_irqsave(inst->hwlock, flags);
if (bch->next_skb) {
printk(KERN_WARNING "%s: next_skb exist ERROR\n", __FUNCTION__);
spin_unlock_irqrestore(inst->hwlock, flags);
return(-EBUSY);
}
if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
bch->next_skb = skb;
spin_unlock_irqrestore(inst->hwlock, flags);
return(0);
} else {
bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len);
bch->tx_idx = 0;
W6692_fill_Bfifo(bch);
spin_unlock_irqrestore(inst->hwlock, flags);
#ifdef FIXME
if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
&& bch->dev)
hif = &bch->dev->rport.pif;
else
hif = &bch->inst.up;
#endif
skb_trim(skb, 0);
return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM,
hh->dinfo, skb));
}
} else if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
(hh->prim == (DL_ESTABLISH | REQUEST))) { (hh->prim == (DL_ESTABLISH | REQUEST))) {
if (!test_and_set_bit(BC_FLG_ACTIV, &bch->Flag)) { if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) {
spin_lock_irqsave(inst->hwlock, flags); spin_lock_irqsave(bch->inst.hwlock, flags);
ret = mode_w6692(bch, bch->channel, bch->inst.pid.protocol[1]); ret = mode_w6692(bch, bch->channel, bch->inst.pid.protocol[1]);
spin_unlock_irqrestore(inst->hwlock, flags); spin_unlock_irqrestore(bch->inst.hwlock, flags);
} }
#ifdef FIXME #ifdef FIXME
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV) if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
@ -1046,19 +1038,29 @@ w6692_l2l1B(mISDNinstance_t *inst, struct sk_buff *skb)
hh->prim | CONFIRM, 0, 0, NULL, 0); hh->prim | CONFIRM, 0, 0, NULL, 0);
#endif #endif
skb_trim(skb, 0); skb_trim(skb, 0);
return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, ret, skb)); return(mISDN_queueup_newhead(&bch->inst, 0,
hh->prim | CONFIRM, ret, skb));
} else if ((hh->prim == (PH_DEACTIVATE | REQUEST)) || } else if ((hh->prim == (PH_DEACTIVATE | REQUEST)) ||
(hh->prim == (DL_RELEASE | REQUEST)) || (hh->prim == (DL_RELEASE | REQUEST)) ||
((hh->prim == (PH_CONTROL | REQUEST) && (hh->dinfo == HW_DEACTIVATE)))) { ((hh->prim == (PH_CONTROL | REQUEST) &&
spin_lock_irqsave(inst->hwlock, flags); (hh->dinfo == HW_DEACTIVATE)))) {
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) { spin_lock_irqsave(bch->inst.hwlock, flags);
if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) {
dev_kfree_skb(bch->next_skb); dev_kfree_skb(bch->next_skb);
bch->next_skb = NULL; bch->next_skb = NULL;
} }
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag); if (bch->tx_skb) {
dev_kfree_skb(bch->tx_skb);
bch->tx_skb = NULL;
}
if (bch->rx_skb) {
dev_kfree_skb(bch->rx_skb);
bch->rx_skb = NULL;
}
test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
mode_w6692(bch, bch->channel, ISDN_PID_NONE); mode_w6692(bch, bch->channel, ISDN_PID_NONE);
test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag); test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
spin_unlock_irqrestore(inst->hwlock, flags); spin_unlock_irqrestore(bch->inst.hwlock, flags);
skb_trim(skb, 0); skb_trim(skb, 0);
if (hh->prim != (PH_CONTROL | REQUEST)) { if (hh->prim != (PH_CONTROL | REQUEST)) {
#ifdef FIXME #ifdef FIXME
@ -1067,11 +1069,12 @@ w6692_l2l1B(mISDNinstance_t *inst, struct sk_buff *skb)
if_link(&bch->dev->rport.pif, if_link(&bch->dev->rport.pif,
hh->prim | CONFIRM, 0, 0, NULL, 0); hh->prim | CONFIRM, 0, 0, NULL, 0);
#endif #endif
if (!mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, 0, skb)) if (!mISDN_queueup_newhead(&bch->inst, 0,
hh->prim | CONFIRM, 0, skb))
return(0); return(0);
} }
} else if (hh->prim == (PH_CONTROL | REQUEST)) { } else if (hh->prim == (PH_CONTROL | REQUEST)) {
spin_lock_irqsave(inst->hwlock, flags); spin_lock_irqsave(bch->inst.hwlock, flags);
if (hh->dinfo == HW_POTS_ON) { if (hh->dinfo == HW_POTS_ON) {
ret = enable_pots(bch); ret = enable_pots(bch);
} else if (hh->dinfo == HW_POTS_OFF) { } else if (hh->dinfo == HW_POTS_OFF) {
@ -1082,64 +1085,32 @@ w6692_l2l1B(mISDNinstance_t *inst, struct sk_buff *skb)
ret = setvolume(bch, 0, skb); ret = setvolume(bch, 0, skb);
} else } else
ret = -EINVAL; ret = -EINVAL;
spin_unlock_irqrestore(inst->hwlock, flags); spin_unlock_irqrestore(bch->inst.hwlock, flags);
} else { } else
printk(KERN_WARNING "%s: unknown prim(%x)\n", ret = -EAGAIN;
__FUNCTION__, hh->prim);
ret = -EINVAL;
}
if (!ret) if (!ret)
dev_kfree_skb(skb); dev_kfree_skb(skb);
return(ret); return(ret);
} }
static int static int
w6692_l1hwD(mISDNinstance_t *inst, struct sk_buff *skb) w6692_dmsg(channel_t *dch, struct sk_buff *skb)
{ {
channel_t *dch = container_of(inst, channel_t, inst);
int ret = 0; int ret = 0;
mISDN_head_t *hh = mISDN_HEAD_P(skb); mISDN_head_t *hh = mISDN_HEAD_P(skb);
u_long flags; u_long flags;
if (hh->prim == PH_DATA_REQ) { if (hh->prim == (PH_SIGNAL | REQUEST)) {
/* check oversize */ spin_lock_irqsave(dch->inst.hwlock, flags);
if (skb->len <= 0) {
printk(KERN_WARNING "%s: skb too small\n", __FUNCTION__);
return(-EINVAL);
}
if (skb->len > MAX_DFRAME_LEN_L1) {
printk(KERN_WARNING "%s: skb too large\n", __FUNCTION__);
return(-EINVAL);
}
/* check for pending next_skb */
spin_lock_irqsave(inst->hwlock, flags);
if (dch->next_skb) {
mISDN_debugprint(&dch->inst, "w6692 l2l1 next_skb exist this shouldn't happen");
spin_unlock_irqrestore(inst->hwlock, flags);
return(-EBUSY);
}
if (test_and_set_bit(FLG_TX_BUSY, &dch->Flags)) {
test_and_set_bit(FLG_TX_NEXT, &dch->Flags);
dch->next_skb = skb;
} else {
dch->tx_skb = skb;
dch->tx_idx = 0;
queue_ch_frame(dch, CONFIRM, hh->dinfo, NULL);
W6692_fill_Dfifo(dch->hw);
}
spin_unlock_irqrestore(inst->hwlock, flags);
return(0);
} else if (hh->prim == (PH_SIGNAL | REQUEST)) {
spin_lock_irqsave(inst->hwlock, flags);
if (hh->dinfo == INFO3_P8) if (hh->dinfo == INFO3_P8)
ph_command(dch->hw, W_L1CMD_AR8); ph_command(dch->hw, W_L1CMD_AR8);
else if (hh->dinfo == INFO3_P10) else if (hh->dinfo == INFO3_P10)
ph_command(dch->hw, W_L1CMD_AR10); ph_command(dch->hw, W_L1CMD_AR10);
else else
ret = -EINVAL; ret = -EINVAL;
spin_unlock_irqrestore(inst->hwlock, flags); spin_unlock_irqrestore(dch->inst.hwlock, flags);
} else if (hh->prim == (PH_CONTROL | REQUEST)) { } else if (hh->prim == (PH_CONTROL | REQUEST)) {
spin_lock_irqsave(inst->hwlock, flags); spin_lock_irqsave(dch->inst.hwlock, flags);
if (hh->dinfo == HW_RESET) { if (hh->dinfo == HW_RESET) {
if (dch->state != W_L1IND_DRD) if (dch->state != W_L1IND_DRD)
ph_command(dch->hw, W_L1CMD_RST); ph_command(dch->hw, W_L1CMD_RST);
@ -1151,6 +1122,15 @@ w6692_l1hwD(mISDNinstance_t *inst, struct sk_buff *skb)
dev_kfree_skb(dch->next_skb); dev_kfree_skb(dch->next_skb);
dch->next_skb = NULL; dch->next_skb = NULL;
} }
if (dch->tx_skb) {
dev_kfree_skb(dch->tx_skb);
dch->tx_skb = NULL;
}
if (dch->rx_skb) {
dev_kfree_skb(dch->rx_skb);
dch->rx_skb = NULL;
}
test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
test_and_clear_bit(FLG_TX_NEXT, &dch->Flags); test_and_clear_bit(FLG_TX_NEXT, &dch->Flags);
test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
@ -1169,15 +1149,51 @@ w6692_l1hwD(mISDNinstance_t *inst, struct sk_buff *skb)
/* !!! not implemented yet */ /* !!! not implemented yet */
} else { } else {
if (dch->debug & L1_DEB_WARN) if (dch->debug & L1_DEB_WARN)
mISDN_debugprint(&dch->inst, "w6692_l1hw unknown ctrl %x", mISDN_debugprint(&dch->inst, "w6692_dmsg unknown ctrl %x",
hh->dinfo); hh->dinfo);
ret = -EINVAL; ret = -EINVAL;
} }
spin_unlock_irqrestore(dch->inst.hwlock, flags);
} else
ret = -EAGAIN;
if (!ret)
dev_kfree_skb(skb);
return(ret);
}
static int
w6692_l2l1(mISDNinstance_t *inst, struct sk_buff *skb)
{
channel_t *chan = container_of(inst, channel_t, inst);
int ret = 0;
mISDN_head_t *hh = mISDN_HEAD_P(skb);
u_long flags;
if ((hh->prim == PH_DATA_REQ) || (hh->prim == DL_DATA_REQ)) {
spin_lock_irqsave(inst->hwlock, flags);
ret = channel_senddata(chan, hh->dinfo, skb);
if (ret > 0) { /* direct TX */
if (test_bit(FLG_BCHANNEL, &chan->Flags))
W6692_fill_Dfifo(chan->hw);
else if (test_bit(FLG_DCHANNEL, &chan->Flags))
W6692_fill_Bfifo(chan);
else
int_error();
ret = 0;
}
spin_unlock_irqrestore(inst->hwlock, flags); spin_unlock_irqrestore(inst->hwlock, flags);
} else { return(ret);
if (dch->debug & L1_DEB_WARN) }
mISDN_debugprint(&dch->inst, "w6692_l1hw unknown prim %x", if (test_bit(FLG_DCHANNEL, &chan->Flags)) {
hh->prim); ret = w6692_dmsg(chan, skb);
if (ret != -EAGAIN)
return(ret);
ret = -EINVAL;
}
if (test_bit(FLG_BCHANNEL, &chan->Flags)) {
ret = w6692_bmsg(chan, skb);
if (ret != -EAGAIN)
return(ret);
ret = -EINVAL; ret = -EINVAL;
} }
if (!ret) if (!ret)
@ -1234,8 +1250,8 @@ release_card(w6692pci *card)
WriteW6692(card, W_XDATA, card->xdata); WriteW6692(card, W_XDATA, card->xdata);
} }
release_region(card->addr, 256); release_region(card->addr, 256);
mISDN_free_bch(&card->bch[1]); mISDN_freechannel(&card->bch[1]);
mISDN_free_bch(&card->bch[0]); mISDN_freechannel(&card->bch[0]);
mISDN_freechannel(&card->dch); mISDN_freechannel(&card->dch);
spin_unlock_irqrestore(&card->lock, flags); spin_unlock_irqrestore(&card->lock, flags);
w6692.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL); w6692.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
@ -1291,18 +1307,13 @@ w6692_manager(void *data, u_int prim, void *arg) {
if (channel == 2) if (channel == 2)
mISDN_setpara(&card->dch, &inst->st->para); mISDN_setpara(&card->dch, &inst->st->para);
else else
bch_set_para(&card->bch[channel], &inst->st->para); mISDN_setpara(&card->bch[channel], &inst->st->para);
break; break;
case MGR_UNREGLAYER | REQUEST: case MGR_UNREGLAYER | REQUEST:
if ((skb = create_link_skb(PH_CONTROL | REQUEST, if ((skb = create_link_skb(PH_CONTROL | REQUEST,
HW_DEACTIVATE, 0, NULL, 0))) { HW_DEACTIVATE, 0, NULL, 0))) {
if (channel == 2) { if (w6692_l2l1(inst, skb))
if (w6692_l1hwD(inst, skb)) dev_kfree_skb(skb);
dev_kfree_skb(skb);
} else {
if (w6692_l2l1B(inst, skb))
dev_kfree_skb(skb);
}
} else } else
printk(KERN_WARNING "no SKB in %s MGR_UNREGLAYER | REQUEST\n", __FUNCTION__); printk(KERN_WARNING "no SKB in %s MGR_UNREGLAYER | REQUEST\n", __FUNCTION__);
w6692.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL); w6692.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
@ -1313,7 +1324,7 @@ w6692_manager(void *data, u_int prim, void *arg) {
if (channel == 2) if (channel == 2)
mISDN_setpara(&card->dch, arg); mISDN_setpara(&card->dch, arg);
else else
bch_set_para(&card->bch[channel], arg); mISDN_setpara(&card->bch[channel], arg);
break; break;
case MGR_RELEASE | INDICATION: case MGR_RELEASE | INDICATION:
if (channel == 2) { if (channel == 2) {
@ -1326,7 +1337,7 @@ w6692_manager(void *data, u_int prim, void *arg) {
if ((channel!=2) && (inst->pid.global == 2)) { if ((channel!=2) && (inst->pid.global == 2)) {
if ((skb = create_link_skb(PH_ACTIVATE | REQUEST, if ((skb = create_link_skb(PH_ACTIVATE | REQUEST,
0, 0, NULL, 0))) { 0, 0, NULL, 0))) {
if (w6692_l2l1B(inst, skb)) if (w6692_l2l1(inst, skb))
dev_kfree_skb(skb); dev_kfree_skb(skb);
} }
if (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS) if (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS)
@ -1374,20 +1385,20 @@ static int __devinit setup_instance(w6692pci *card)
card->dch.inst.class_dev.dev = &card->pdev->dev; card->dch.inst.class_dev.dev = &card->pdev->dev;
card->dch.inst.pid.layermask = ISDN_LAYER(0); card->dch.inst.pid.layermask = ISDN_LAYER(0);
card->dch.inst.pid.protocol[0] = ISDN_PID_L0_TE_S0; card->dch.inst.pid.protocol[0] = ISDN_PID_L0_TE_S0;
mISDN_init_instance(&card->dch.inst, &w6692, card, w6692_l1hwD); mISDN_init_instance(&card->dch.inst, &w6692, card, w6692_l2l1);
sprintf(card->dch.inst.name, "W6692_%d", w6692_cnt+1); sprintf(card->dch.inst.name, "W6692_%d", w6692_cnt+1);
mISDN_set_dchannel_pid(&pid, protocol[w6692_cnt], layermask[w6692_cnt]); mISDN_set_dchannel_pid(&pid, protocol[w6692_cnt], layermask[w6692_cnt]);
mISDN_initchannel(&card->dch, MSK_DCHANNEL, MAX_DFRAME_LEN_L1); mISDN_initchannel(&card->dch, MSK_INIT_DCHANNEL, MAX_DFRAME_LEN_L1);
card->dch.hw = card; card->dch.hw = card;
for (i=0; i<2; i++) { for (i=0; i<2; i++) {
card->bch[i].channel = i; card->bch[i].channel = i;
mISDN_init_instance(&card->bch[i].inst, &w6692, card, w6692_l2l1B); mISDN_init_instance(&card->bch[i].inst, &w6692, card, w6692_l2l1);
card->bch[i].inst.pid.layermask = ISDN_LAYER(0); card->bch[i].inst.pid.layermask = ISDN_LAYER(0);
card->bch[i].inst.hwlock = &card->lock; card->bch[i].inst.hwlock = &card->lock;
card->bch[i].inst.class_dev.dev = &card->pdev->dev; card->bch[i].inst.class_dev.dev = &card->pdev->dev;
card->bch[i].debug = debug; card->bch[i].debug = debug;
sprintf(card->bch[i].inst.name, "%s B%d", card->dch.inst.name, i+1); sprintf(card->bch[i].inst.name, "%s B%d", card->dch.inst.name, i+1);
mISDN_init_bch(&card->bch[i]); mISDN_initchannel(&card->bch[i], MSK_INIT_BCHANNEL, MAX_DATA_MEM);
card->bch[i].hw = &card->wbc[i]; card->bch[i].hw = &card->wbc[i];
} }
if (debug) if (debug)
@ -1396,8 +1407,8 @@ static int __devinit setup_instance(w6692pci *card)
err = setup_w6692(card); err = setup_w6692(card);
if (err) { if (err) {
mISDN_freechannel(&card->dch); mISDN_freechannel(&card->dch);
mISDN_free_bch(&card->bch[1]); mISDN_freechannel(&card->bch[1]);
mISDN_free_bch(&card->bch[0]); mISDN_freechannel(&card->bch[0]);
list_del(&card->list); list_del(&card->list);
kfree(card); kfree(card);
return(err); return(err);