parent
ab7fd00493
commit
32dd9af3eb
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue