- move remaining HW drivers to mISDN

- fix possible race ->next_skb usage
- helper for sending bchannel DATA INDICATION and CONFIRM
This commit is contained in:
Karsten Keil 2005-10-27 19:23:39 +00:00
parent e872a653bd
commit 9f4e63a6c0
8 changed files with 400 additions and 603 deletions

View File

@ -21,7 +21,6 @@
#include "bchannel.h" #include "bchannel.h"
#include "isac.h" #include "isac.h"
#include "layer1.h" #include "layer1.h"
#include "helper.h"
#include "debug.h" #include "debug.h"
#define SPIN_DEBUG #define SPIN_DEBUG
@ -282,7 +281,7 @@ __write_ctrl_pciv2(fritzpnppci *fc, hdlc_hw_t *hdlc, int channel) {
void void
write_ctrl(bchannel_t *bch, int which) { write_ctrl(bchannel_t *bch, int which) {
fritzpnppci *fc = bch->inst.data; fritzpnppci *fc = bch->inst.privat;
hdlc_hw_t *hdlc = bch->hw; hdlc_hw_t *hdlc = bch->hw;
if (fc->dch.debug & L1_DEB_HSCX) if (fc->dch.debug & L1_DEB_HSCX)
@ -374,7 +373,7 @@ modehdlc(bchannel_t *bch, int bc, int protocol)
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS; hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
write_ctrl(bch, 1); write_ctrl(bch, 1);
hdlc->ctrl.sr.cmd = 0; hdlc->ctrl.sr.cmd = 0;
bch_sched_event(bch, B_XMTBUFREADY); // FIXME bch_sched_event(bch, B_XMTBUFREADY);
break; break;
case (ISDN_PID_L1_B_64HDLC): case (ISDN_PID_L1_B_64HDLC):
bch->protocol = protocol; bch->protocol = protocol;
@ -384,7 +383,7 @@ modehdlc(bchannel_t *bch, int bc, int protocol)
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS; hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
write_ctrl(bch, 1); write_ctrl(bch, 1);
hdlc->ctrl.sr.cmd = 0; hdlc->ctrl.sr.cmd = 0;
bch_sched_event(bch, B_XMTBUFREADY); // FIXME bch_sched_event(bch, B_XMTBUFREADY);
break; break;
default: default:
mISDN_debugprint(&bch->inst, "prot not known %x", protocol); mISDN_debugprint(&bch->inst, "prot not known %x", protocol);
@ -400,7 +399,7 @@ hdlc_empty_fifo(bchannel_t *bch, int count)
u_char *p; u_char *p;
u_char idx = bch->channel ? AVM_HDLC_2 : AVM_HDLC_1; u_char idx = bch->channel ? AVM_HDLC_2 : AVM_HDLC_1;
int cnt=0; int cnt=0;
fritzpnppci *fc = bch->inst.data; fritzpnppci *fc = bch->inst.privat;
if ((fc->dch.debug & L1_DEB_HSCX) && !(fc->dch.debug & L1_DEB_HSCX_FIFO)) if ((fc->dch.debug & L1_DEB_HSCX) && !(fc->dch.debug & L1_DEB_HSCX_FIFO))
mISDN_debugprint(&bch->inst, "hdlc_empty_fifo %d", count); mISDN_debugprint(&bch->inst, "hdlc_empty_fifo %d", count);
@ -463,7 +462,7 @@ hdlc_empty_fifo(bchannel_t *bch, int count)
static void static void
hdlc_fill_fifo(bchannel_t *bch) hdlc_fill_fifo(bchannel_t *bch)
{ {
fritzpnppci *fc = bch->inst.data; fritzpnppci *fc = bch->inst.privat;
hdlc_hw_t *hdlc = bch->hw; hdlc_hw_t *hdlc = bch->hw;
int count, cnt =0; int count, cnt =0;
u_char *p; u_char *p;
@ -542,21 +541,28 @@ HDLC_irq_xpr(bchannel_t *bch)
hdlc_fill_fifo(bch); hdlc_fill_fifo(bch);
else { else {
bch->tx_idx = 0; bch->tx_idx = 0;
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) { if (test_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
if (bch->next_skb) { struct sk_buff *skb = bch->next_skb;
bch->tx_len = bch->next_skb->len; mISDN_head_t *hh;
memcpy(bch->tx_buf, bch->next_skb->data, bch->tx_len); if (skb) {
bch->next_skb = NULL;
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
hh = mISDN_HEAD_P(skb);
bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len);
hdlc_fill_fifo(bch); hdlc_fill_fifo(bch);
skb_trim(skb, 0);
queue_bch_frame(bch, CONFIRM, hh->dinfo, skb);
} else { } else {
bch->tx_len = 0; bch->tx_len = 0;
printk(KERN_WARNING "hdlc tx irq TX_NEXT without skb\n"); printk(KERN_WARNING "hdlc tx irq TX_NEXT without skb\n");
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag); test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
} }
} else { } else {
bch->tx_len = 0; bch->tx_len = 0;
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag); test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
} }
bch_sched_event(bch, B_XMTBUFREADY);
} }
} }
@ -593,10 +599,9 @@ HDLC_irq(bchannel_t *bch, u_int stat)
else { else {
memcpy(skb_put(skb, bch->rx_idx), memcpy(skb_put(skb, bch->rx_idx),
bch->rx_buf, bch->rx_idx); bch->rx_buf, bch->rx_idx);
skb_queue_tail(&bch->rqueue, skb); queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
} }
bch->rx_idx = 0; bch->rx_idx = 0;
bch_sched_event(bch, B_RCVBUFREADY);
} else { } else {
if (bch->debug & L1_DEB_HSCX) if (bch->debug & L1_DEB_HSCX)
mISDN_debugprint(&bch->inst, "invalid frame"); mISDN_debugprint(&bch->inst, "invalid frame");
@ -811,54 +816,52 @@ avm_fritzv2_interrupt(int intno, void *dev_id, struct pt_regs *regs)
} }
static int static int
hdlc_down(mISDNif_t *hif, struct sk_buff *skb) hdlc_down(mISDNinstance_t *inst, struct sk_buff *skb)
{ {
bchannel_t *bch; bchannel_t *bch;
int ret = -EINVAL; int ret = 0;
mISDN_head_t *hh; mISDN_head_t *hh;
if (!hif || !skb)
return(ret);
hh = mISDN_HEAD_P(skb); hh = mISDN_HEAD_P(skb);
bch = hif->fdata; bch = container_of(inst, bchannel_t, inst);
if ((hh->prim == PH_DATA_REQ) || if ((hh->prim == PH_DATA_REQ) ||
(hh->prim == (DL_DATA | REQUEST))) { (hh->prim == (DL_DATA | REQUEST))) {
if (bch->next_skb) { if (bch->next_skb) {
mISDN_debugprint(&bch->inst, " l2l1 next_skb exist this shouldn't happen"); mISDN_debugprint(&bch->inst, " l2l1 next_skb exist this shouldn't happen");
return(-EBUSY); return(-EBUSY);
} }
bch->inst.lock(bch->inst.data, 0); if (skb->len <= 0)
return(-EINVAL);
bch->inst.lock(bch->inst.privat, 0);
if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) { if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag); test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
bch->next_skb = skb; bch->next_skb = skb;
bch->inst.unlock(bch->inst.data); bch->inst.unlock(bch->inst.privat);
return(0); return(0);
} else { } else {
bch->tx_len = skb->len; bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len); memcpy(bch->tx_buf, skb->data, bch->tx_len);
bch->tx_idx = 0; bch->tx_idx = 0;
hdlc_fill_fifo(bch); hdlc_fill_fifo(bch);
bch->inst.unlock(bch->inst.data); bch->inst.unlock(bch->inst.privat);
skb_trim(skb, 0); skb_trim(skb, 0);
return(if_newhead(&bch->inst.up, hh->prim | CONFIRM, return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM,
hh->dinfo, skb)); hh->dinfo, skb));
} }
} else if ((hh->prim == (PH_ACTIVATE | REQUEST)) || } 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(BC_FLG_ACTIV, &bch->Flag)) {
ret = 0; bch->inst.lock(bch->inst.privat,0);
else {
bch->inst.lock(bch->inst.data,0);
ret = modehdlc(bch, bch->channel, ret = modehdlc(bch, bch->channel,
bch->inst.pid.protocol[1]); bch->inst.pid.protocol[1]);
bch->inst.unlock(bch->inst.data); bch->inst.unlock(bch->inst.privat);
} }
skb_trim(skb, 0); skb_trim(skb, 0);
return(if_newhead(&bch->inst.up, hh->prim | CONFIRM, ret, skb)); return(mISDN_queueup_newhead(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 == (MGR_DISCONNECT | REQUEST))) { ((hh->prim == (PH_CONTROL | REQUEST) && (hh->dinfo == HW_DEACTIVATE)))) {
bch->inst.lock(bch->inst.data,0); bch->inst.lock(bch->inst.privat,0);
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) { if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
dev_kfree_skb(bch->next_skb); dev_kfree_skb(bch->next_skb);
bch->next_skb = NULL; bch->next_skb = NULL;
@ -866,12 +869,10 @@ hdlc_down(mISDNif_t *hif, struct sk_buff *skb)
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag); test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
modehdlc(bch, bch->channel, 0); modehdlc(bch, bch->channel, 0);
test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag); test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag);
bch->inst.unlock(bch->inst.data); bch->inst.unlock(bch->inst.privat);
skb_trim(skb, 0); skb_trim(skb, 0);
if (hh->prim != (MGR_DISCONNECT | REQUEST)) if (hh->prim != (PH_CONTROL | REQUEST))
if (!if_newhead(&bch->inst.up, hh->prim | CONFIRM, 0, skb)) ret = mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, 0, skb);
return(0);
ret = 0;
} else { } else {
printk(KERN_WARNING "hdlc_down unknown prim(%x)\n", hh->prim); printk(KERN_WARNING "hdlc_down unknown prim(%x)\n", hh->prim);
ret = -EINVAL; ret = -EINVAL;
@ -1108,7 +1109,6 @@ release_card(fritzpnppci *card)
mISDN_free_bch(&card->bch[1]); mISDN_free_bch(&card->bch[1]);
mISDN_free_bch(&card->bch[0]); mISDN_free_bch(&card->bch[0]);
mISDN_free_dch(&card->dch); mISDN_free_dch(&card->dch);
fritz.ctrl(card->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &card->dch.inst.up);
fritz.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL); fritz.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
list_del(&card->list); list_del(&card->list);
unlock_dev(card); unlock_dev(card);
@ -1166,22 +1166,17 @@ fritz_manager(void *data, u_int prim, void *arg) {
bch_set_para(&card->bch[channel], &inst->st->para); bch_set_para(&card->bch[channel], &inst->st->para);
break; break;
case MGR_UNREGLAYER | REQUEST: case MGR_UNREGLAYER | REQUEST:
if (channel == 2) {
inst->down.fdata = &card->dch;
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 (mISDN_ISAC_l1hw(&inst->down, skb)) if (channel == 2) {
if (mISDN_ISAC_l1hw(inst, skb))
dev_kfree_skb(skb); dev_kfree_skb(skb);
}
} else { } else {
inst->down.fdata = &card->bch[channel]; if (hdlc_down(inst, skb))
if ((skb = create_link_skb(MGR_DISCONNECT | REQUEST,
0, 0, NULL, 0))) {
if (hdlc_down(&inst->down, skb))
dev_kfree_skb(skb); dev_kfree_skb(skb);
} }
} } else
fritz.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up); printk(KERN_WARNING "no SKB in %s MGR_UNREGLAYER | REQUEST\n", __FUNCTION__);
fritz.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL); fritz.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
break; break;
case MGR_CLRSTPARA | INDICATION: case MGR_CLRSTPARA | INDICATION:
@ -1199,33 +1194,18 @@ fritz_manager(void *data, u_int prim, void *arg) {
fritz.refcnt--; fritz.refcnt--;
} }
break; break;
case MGR_CONNECT | REQUEST:
return(mISDN_ConnectIF(inst, arg));
case MGR_SETIF | REQUEST:
case MGR_SETIF | INDICATION:
if (channel==2)
return(mISDN_SetIF(inst, arg, prim, mISDN_ISAC_l1hw, NULL,
&card->dch));
else
return(mISDN_SetIF(inst, arg, prim, hdlc_down, NULL,
&card->bch[channel]));
break;
case MGR_DISCONNECT | REQUEST:
case MGR_DISCONNECT | INDICATION:
return(mISDN_DisConnectIF(inst, arg));
case MGR_SETSTACK | INDICATION: case MGR_SETSTACK | INDICATION:
if ((channel!=2) && (inst->pid.global == 2)) { if ((channel!=2) && (inst->pid.global == 2)) {
inst->down.fdata = &card->bch[channel];
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 (hdlc_down(&inst->down, skb)) if (hdlc_down(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)
if_link(&inst->up, DL_ESTABLISH | INDICATION, mISDN_queue_data(inst, FLG_MSG_UP, DL_ESTABLISH | INDICATION,
0, 0, NULL, 0); 0, 0, NULL, 0);
else else
if_link(&inst->up, PH_ACTIVATE | INDICATION, mISDN_queue_data(inst, FLG_MSG_UP, PH_ACTIVATE | INDICATION,
0, 0, NULL, 0); 0, 0, NULL, 0);
} }
break; break;
@ -1251,13 +1231,13 @@ static int __devinit setup_instance(fritzpnppci *card)
card->dch.inst.unlock = unlock_dev; card->dch.inst.unlock = unlock_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, &fritz, card); mISDN_init_instance(&card->dch.inst, &fritz, card, mISDN_ISAC_l1hw);
sprintf(card->dch.inst.name, "Fritz%d", fritz_cnt+1); sprintf(card->dch.inst.name, "Fritz%d", fritz_cnt+1);
mISDN_set_dchannel_pid(&pid, protocol[fritz_cnt], layermask[fritz_cnt]); mISDN_set_dchannel_pid(&pid, protocol[fritz_cnt], layermask[fritz_cnt]);
mISDN_init_dch(&card->dch); mISDN_init_dch(&card->dch);
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, &fritz, card); mISDN_init_instance(&card->bch[i].inst, &fritz, card, hdlc_down);
card->bch[i].inst.pid.layermask = ISDN_LAYER(0); card->bch[i].inst.pid.layermask = ISDN_LAYER(0);
card->bch[i].inst.lock = lock_dev; card->bch[i].inst.lock = lock_dev;
card->bch[i].inst.unlock = unlock_dev; card->bch[i].inst.unlock = unlock_dev;

View File

@ -5,7 +5,8 @@
* This file is (c) under GNU PUBLIC LICENSE * This file is (c) under GNU PUBLIC LICENSE
* *
*/ */
#ifndef _mISDN_BCHANNEL_H
#define _mISDN_BCHANNEL_H
#include <linux/mISDNif.h> #include <linux/mISDNif.h>
#ifdef HAS_WORKQUEUE #ifdef HAS_WORKQUEUE
#include <linux/workqueue.h> #include <linux/workqueue.h>
@ -22,6 +23,7 @@
#ifdef MISDN_MEMDEBUG #ifdef MISDN_MEMDEBUG
#include "memdbg.h" #include "memdbg.h"
#endif #endif
#include "helper.h"
#define MAX_BLOG_SPACE 256 #define MAX_BLOG_SPACE 256
@ -92,6 +94,19 @@ bch_set_para(bchannel_t *bch, mISDN_stPara_t *stp)
} }
} }
static inline void
queue_bch_frame(bchannel_t *bch, u_int pr, int dinfo, struct sk_buff *skb)
{
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
pr |= DL_DATA;
else
pr |= PH_DATA;
if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, dinfo, skb))) {
int_error();
dev_kfree_skb(skb);
}
}
#ifdef OBSOLETE #ifdef OBSOLETE
static inline void static inline void
bch_sched_event(bchannel_t *bch, int event) bch_sched_event(bchannel_t *bch, int event)
@ -100,3 +115,4 @@ bch_sched_event(bchannel_t *bch, int event)
schedule_work(&bch->work); schedule_work(&bch->work);
} }
#endif #endif
#endif

View File

@ -101,7 +101,6 @@
#include "bchannel.h" #include "bchannel.h"
#include "layer1.h" #include "layer1.h"
#include "dsp.h" #include "dsp.h"
#include "helper.h"
#include "debug.h" #include "debug.h"
#include <linux/isdn_compat.h> #include <linux/isdn_compat.h>
@ -1013,11 +1012,12 @@ next_frame:
} */ } */
// check for next frame // check for next frame
if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) { if (test_bit(FLG_TX_NEXT, &dch->DFlags)) {
struct sk_buff *skb = dch->next_skb; struct sk_buff *skb = dch->next_skb;
mISDN_head_t *hh; mISDN_head_t *hh;
if (skb) { if (skb) {
dch->next_skb = NULL; dch->next_skb = NULL;
test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
hh = mISDN_HEAD_P(skb); hh = mISDN_HEAD_P(skb);
dch->tx_idx = 0; dch->tx_idx = 0;
dch->tx_len = skb->len; dch->tx_len = skb->len;
@ -1025,38 +1025,35 @@ next_frame:
skb_trim(skb, 0); skb_trim(skb, 0);
if (mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_CNF, hh->dinfo, skb)) dev_kfree_skb(skb); if (mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_CNF, hh->dinfo, skb)) dev_kfree_skb(skb);
goto next_frame; goto next_frame;
} else } else {
test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
printk(KERN_WARNING "%s: tx irq TX_NEXT without skb (dch ch=%d)\n", __FUNCTION__, ch); printk(KERN_WARNING "%s: tx irq TX_NEXT without skb (dch ch=%d)\n", __FUNCTION__, ch);
} }
}
test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags); test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
dch->tx_idx = dch->tx_len = 0; dch->tx_idx = dch->tx_len = 0;
} }
if (bch) { if (bch) {
// check for next frame // check for next frame
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) { if (test_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
struct sk_buff *skb = bch->next_skb; struct sk_buff *skb = bch->next_skb;
mISDN_head_t *hh; mISDN_head_t *hh;
u_int pr;
if (skb) { if (skb) {
bch->next_skb = NULL; bch->next_skb = NULL;
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
hh = mISDN_HEAD_P(skb); hh = mISDN_HEAD_P(skb);
bch->tx_idx = 0; bch->tx_idx = 0;
bch->tx_len = skb->len; bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len); memcpy(bch->tx_buf, skb->data, bch->tx_len);
skb_trim(skb, 0); skb_trim(skb, 0);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS) queue_bch_frame(bch, CONFIRM, hh->dinfo, skb);
pr = DL_DATA | CONFIRM;
else
pr = PH_DATA | CONFIRM;
if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, hh->dinfo, skb))) {
int_error();
dev_kfree_skb(skb);
}
goto next_frame; goto next_frame;
} else } else {
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n"); printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
} }
}
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag); test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
bch->tx_idx = bch->tx_len = 0; bch->tx_idx = bch->tx_len = 0;
@ -1262,17 +1259,8 @@ next_frame:
// schedule D-channel event // schedule D-channel event
mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_IND, MISDN_ID_ANY, skb); mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_IND, MISDN_ID_ANY, skb);
} }
if (bch) { if (bch)
// schedule B-channel event queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
pr = DL_DATA | INDICATION;
else
pr = PH_DATA | INDICATION;
if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, MISDN_ID_ANY, skb))) {
int_error();
dev_kfree_skb(skb);
}
}
*idx = 0; *idx = 0;
goto next_frame; goto next_frame;
} }
@ -1301,19 +1289,8 @@ next_frame:
//dchannel_sched_event(dch, D_RCVBUFREADY); //dchannel_sched_event(dch, D_RCVBUFREADY);
mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_IND, MISDN_ID_ANY, skb); mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_IND, MISDN_ID_ANY, skb);
} }
if (bch) { if (bch)
// schedule B-channel event queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
//skb_queue_tail(&bch->rqueue, skb);
//bch_sched_event(bch, B_RCVBUFREADY);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
pr = DL_DATA | INDICATION;
else
pr = PH_DATA | INDICATION;
if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, MISDN_ID_ANY, skb))) {
int_error();
dev_kfree_skb(skb);
}
}
} }
} }

View File

@ -34,7 +34,6 @@
#include "bchannel.h" #include "bchannel.h"
#include "hfc_pci.h" #include "hfc_pci.h"
#include "layer1.h" #include "layer1.h"
#include "helper.h"
#include "debug.h" #include "debug.h"
#include <linux/isdn_compat.h> #include <linux/isdn_compat.h>
@ -546,7 +545,6 @@ hfcpci_empty_fifo_trans(bchannel_t *bch, bzfifo_type * bz, u_char * bdata)
{ {
unsigned short *z1r, *z2r; unsigned short *z1r, *z2r;
int new_z2, fcnt, maxlen; int new_z2, fcnt, maxlen;
u_int pr;
struct sk_buff *skb; struct sk_buff *skb;
u_char *ptr, *ptr1; u_char *ptr, *ptr1;
@ -583,14 +581,7 @@ hfcpci_empty_fifo_trans(bchannel_t *bch, bzfifo_type * bz, u_char * bdata)
ptr1 = bdata; /* start of buffer */ ptr1 = bdata; /* start of buffer */
memcpy(ptr, ptr1, fcnt); /* rest */ memcpy(ptr, ptr1, fcnt); /* rest */
} }
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS) queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
pr = DL_DATA | INDICATION;
else
pr = PH_DATA | INDICATION;
if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, MISDN_ID_ANY, skb))) {
int_error();
dev_kfree_skb(skb);
}
} }
*z2r = new_z2; /* new position */ *z2r = new_z2; /* new position */
@ -606,7 +597,6 @@ main_rec_hfcpci(bchannel_t *bch)
hfc_pci_t *hc = bch->hw; hfc_pci_t *hc = bch->hw;
int rcnt, real_fifo; int rcnt, real_fifo;
int receive, count = 5; int receive, count = 5;
u_int pr;
struct sk_buff *skb; struct sk_buff *skb;
bzfifo_type *bz; bzfifo_type *bz;
u_char *bdata; u_char *bdata;
@ -638,14 +628,7 @@ main_rec_hfcpci(bchannel_t *bch)
mISDN_debugprint(&bch->inst, "hfcpci rec ch(%x) z1(%x) z2(%x) cnt(%d)", mISDN_debugprint(&bch->inst, "hfcpci rec ch(%x) z1(%x) z2(%x) cnt(%d)",
bch->channel, zp->z1, zp->z2, rcnt); bch->channel, zp->z1, zp->z2, rcnt);
if ((skb = hfcpci_empty_fifo(bch, bz, bdata, rcnt))) { if ((skb = hfcpci_empty_fifo(bch, bz, bdata, rcnt))) {
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS) queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
pr = DL_DATA | INDICATION;
else
pr = PH_DATA | INDICATION;
if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, MISDN_ID_ANY, skb))) {
int_error();
dev_kfree_skb(skb);
}
} }
rcnt = bz->f1 - bz->f2; rcnt = bz->f1 - bz->f2;
if (rcnt < 0) if (rcnt < 0)
@ -814,29 +797,24 @@ next_t_frame:
} else if (bch->debug & L1_DEB_HSCX) } else if (bch->debug & L1_DEB_HSCX)
mISDN_debugprint(&bch->inst, "hfcpci_fill_fifo_trans ch(%x) frame length %d discarded", mISDN_debugprint(&bch->inst, "hfcpci_fill_fifo_trans ch(%x) frame length %d discarded",
bch->channel, bch->tx_len); bch->channel, bch->tx_len);
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) { if (test_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
struct sk_buff *skb = bch->next_skb; struct sk_buff *skb = bch->next_skb;
mISDN_head_t *hh; mISDN_head_t *hh;
u_int pr;
if (skb) { if (skb) {
bch->next_skb = NULL; bch->next_skb = NULL;
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
hh = mISDN_HEAD_P(skb); hh = mISDN_HEAD_P(skb);
bch->tx_idx = 0; bch->tx_idx = 0;
bch->tx_len = skb->len; bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len); memcpy(bch->tx_buf, skb->data, bch->tx_len);
skb_trim(skb, 0); skb_trim(skb, 0);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS) queue_bch_frame(bch, CONFIRM, hh->dinfo, skb);
pr = DL_DATA | CONFIRM;
else
pr = PH_DATA | CONFIRM;
if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, hh->dinfo, skb))) {
int_error();
dev_kfree_skb(skb);
}
goto next_t_frame; goto next_t_frame;
} else } else {
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n"); printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
} }
}
bch->tx_len = 0; bch->tx_len = 0;
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag); test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
bch->tx_idx = bch->tx_len; bch->tx_idx = bch->tx_len;
@ -1288,28 +1266,22 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
hfcpci_fill_fifo(bch); hfcpci_fill_fifo(bch);
} else { } else {
bch->tx_idx = 0; bch->tx_idx = 0;
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) { if (test_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
struct sk_buff *skb = bch->next_skb; struct sk_buff *skb = bch->next_skb;
mISDN_head_t *hh; mISDN_head_t *hh;
u_int pr;
if (skb) { if (skb) {
bch->next_skb = NULL; bch->next_skb = NULL;
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
hh = mISDN_HEAD_P(skb); hh = mISDN_HEAD_P(skb);
bch->tx_idx = 0; bch->tx_idx = 0;
bch->tx_len = skb->len; bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len); memcpy(bch->tx_buf, skb->data, bch->tx_len);
skb_trim(skb, 0); skb_trim(skb, 0);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS) queue_bch_frame(bch, CONFIRM, hh->dinfo, skb);
pr = DL_DATA | CONFIRM;
else
pr = PH_DATA | CONFIRM;
if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, hh->dinfo, skb))) {
int_error();
dev_kfree_skb(skb);
}
hfcpci_fill_fifo(bch); hfcpci_fill_fifo(bch);
} else { } else {
printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n"); printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag); test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
bch->tx_len = 0; bch->tx_len = 0;
} }
@ -1330,28 +1302,22 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
hfcpci_fill_fifo(bch); hfcpci_fill_fifo(bch);
} else { } else {
bch->tx_idx = 0; bch->tx_idx = 0;
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) { if (test_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
struct sk_buff *skb = bch->next_skb; struct sk_buff *skb = bch->next_skb;
mISDN_head_t *hh; mISDN_head_t *hh;
u_int pr;
if (skb) { if (skb) {
bch->next_skb = NULL; bch->next_skb = NULL;
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
hh = mISDN_HEAD_P(skb); hh = mISDN_HEAD_P(skb);
bch->tx_idx = 0; bch->tx_idx = 0;
bch->tx_len = skb->len; bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len); memcpy(bch->tx_buf, skb->data, bch->tx_len);
skb_trim(skb, 0); skb_trim(skb, 0);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS) queue_bch_frame(bch, CONFIRM, hh->dinfo, skb);
pr = DL_DATA | CONFIRM;
else
pr = PH_DATA | CONFIRM;
if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, hh->dinfo, skb))) {
int_error();
dev_kfree_skb(skb);
}
hfcpci_fill_fifo(bch); hfcpci_fill_fifo(bch);
} else { } else {
printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n"); printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag); test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
bch->tx_len = 0; bch->tx_len = 0;
} }
@ -1376,22 +1342,23 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
if (hc->dch.tx_idx < hc->dch.tx_len) { if (hc->dch.tx_idx < hc->dch.tx_len) {
hfcpci_fill_dfifo(hc); hfcpci_fill_dfifo(hc);
} else { } else {
if (test_and_clear_bit(FLG_TX_NEXT, &hc->dch.DFlags)) { if (test_bit(FLG_TX_NEXT, &hc->dch.DFlags)) {
if (hc->dch.next_skb) { struct sk_buff *skb = hc->dch.next_skb;
mISDN_head_t *hh; if (skb) {
hc->dch.tx_len = hc->dch.next_skb->len; mISDN_head_t *hh = mISDN_HEAD_P(skb);
memcpy(hc->dch.tx_buf,
hc->dch.next_skb->data, hc->dch.next_skb= NULL;
hc->dch.tx_len); test_and_clear_bit(FLG_TX_NEXT, &hc->dch.DFlags);
hc->dch.tx_len = skb->len;
memcpy(hc->dch.tx_buf, skb->data, hc->dch.tx_len);
hc->dch.tx_idx = 0; hc->dch.tx_idx = 0;
hfcpci_fill_dfifo(hc); hfcpci_fill_dfifo(hc);
skb_trim(hc->dch.next_skb, 0); skb_trim(skb, 0);
hh = mISDN_HEAD_P(hc->dch.next_skb); if (mISDN_queueup_newhead(&hc->dch.inst, 0, PH_DATA_CNF, hh->dinfo, skb))
if (mISDN_queueup_newhead(&hc->dch.inst, 0, PH_DATA_CNF, hh->dinfo, hc->dch.next_skb)) dev_kfree_skb(skb);
dev_kfree_skb(hc->dch.next_skb);
hc->dch.next_skb= NULL;
} else { } else {
printk(KERN_WARNING "hfcd tx irq TX_NEXT without skb\n"); printk(KERN_WARNING "hfcd tx irq TX_NEXT without skb\n");
test_and_clear_bit(FLG_TX_NEXT, &hc->dch.DFlags);
test_and_clear_bit(FLG_TX_BUSY, &hc->dch.DFlags); test_and_clear_bit(FLG_TX_BUSY, &hc->dch.DFlags);
} }
} else } else
@ -1432,13 +1399,12 @@ HFCD_l1hw(mISDNinstance_t *inst, struct sk_buff *skb)
{ {
dchannel_t *dch; dchannel_t *dch;
hfc_pci_t *hc; hfc_pci_t *hc;
int ret = -EINVAL; int ret = 0;
mISDN_head_t *hh; mISDN_head_t *hh;
hh = mISDN_HEAD_P(skb); hh = mISDN_HEAD_P(skb);
dch = container_of(inst, dchannel_t, inst); dch = container_of(inst, dchannel_t, inst);
hc = inst->privat; hc = inst->privat;
ret = 0;
if (hh->prim == PH_DATA_REQ) { if (hh->prim == PH_DATA_REQ) {
if (dch->next_skb) { if (dch->next_skb) {
printk(KERN_WARNING "%s: next_skb exist ERROR\n", __FUNCTION__); printk(KERN_WARNING "%s: next_skb exist ERROR\n", __FUNCTION__);
@ -1571,7 +1537,7 @@ HFCD_l1hw(mISDNinstance_t *inst, struct sk_buff *skb)
test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags); test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags)) if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
del_timer(&dch->dbusytimer); del_timer(&dch->dbusytimer);
#if 0 #ifdef FIXME
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags)) if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
dchannel_sched_event(&hc->dch, D_CLEARBUSY); dchannel_sched_event(&hc->dch, D_CLEARBUSY);
#endif #endif
@ -1884,12 +1850,13 @@ hfcpci_l2l1(mISDNinstance_t *inst, struct sk_buff *skb)
hh = mISDN_HEAD_P(skb); hh = mISDN_HEAD_P(skb);
if ((hh->prim == PH_DATA_REQ) || if ((hh->prim == PH_DATA_REQ) ||
(hh->prim == (DL_DATA | REQUEST))) { (hh->prim == (DL_DATA | REQUEST))) {
#warning TODO: hier muss abgefragt werden, ob skb->len <= 0 ist, und ggf. ein -EINVAL zurückliefern, sonst wird zwar einmal confirmed, aber es regt sich nichts mehr. dies bitte auch für den d-kanal überdenken, sowie für alle andere kartentreiber.
if (bch->next_skb) { if (bch->next_skb) {
printk(KERN_WARNING "%s: next_skb exist ERROR\n", printk(KERN_WARNING "%s: next_skb exist ERROR\n",
__FUNCTION__); __FUNCTION__);
return(-EBUSY); return(-EBUSY);
} }
if (skb->len <= 0)
return(-EINVAL);
bch->inst.lock(hc, 0); bch->inst.lock(hc, 0);
if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) { if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag); test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);

View File

@ -35,7 +35,6 @@
#include "dchannel.h" #include "dchannel.h"
#include "bchannel.h" #include "bchannel.h"
#include "layer1.h" #include "layer1.h"
#include "helper.h"
#include "debug.h" #include "debug.h"
#include "hw_lock.h" #include "hw_lock.h"
#include "hfcs_usb.h" #include "hfcs_usb.h"
@ -221,8 +220,8 @@ static struct usb_device_id hfcsusb_idtab[] = {
}; };
/* some function prototypes */ /* some function prototypes */
static int hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb); static int hfcsusb_l1hwD(mISDNinstance_t *inst, struct sk_buff *skb);
static int hfcsusb_l2l1B(mISDNif_t * hif, struct sk_buff *skb); static int hfcsusb_l2l1B(mISDNinstance_t *inst, struct sk_buff *skb);
static int mode_bchannel(bchannel_t * bch, int bc, int protocol); static int mode_bchannel(bchannel_t * bch, int bc, int protocol);
static void hfcsusb_ph_command(hfcsusb_t * card, u_char command); static void hfcsusb_ph_command(hfcsusb_t * card, u_char command);
@ -433,32 +432,18 @@ hfcsusb_manager(void *data, u_int prim, void *arg)
&inst->st->para); &inst->st->para);
break; break;
case MGR_UNREGLAYER | REQUEST: case MGR_UNREGLAYER | REQUEST:
if ((skb = create_link_skb(PH_CONTROL | REQUEST,
HW_DEACTIVATE, 0, NULL, 0))) {
if (channel == 2) { if (channel == 2) {
inst->down.fdata = &card->dch; if (hfcsusb_l1hwD(inst, skb))
if ((skb =
create_link_skb(PH_CONTROL | REQUEST,
HW_DEACTIVATE, 0,
NULL, 0))) {
if (hfcsusb_l1hwD
(&inst->down, skb))
dev_kfree_skb(skb); dev_kfree_skb(skb);
}
} else { } else {
inst->down.fdata = &card->bch[channel]; if (hfcsusb_l2l1B(inst, skb))
if ((skb =
create_link_skb(MGR_DISCONNECT |
REQUEST, 0, 0, NULL,
0))) {
if (hfcsusb_l2l1B
(&inst->down, skb))
dev_kfree_skb(skb); dev_kfree_skb(skb);
} }
} } else
hw_mISDNObj.ctrl(inst->up.peer, printk(KERN_WARNING "no SKB in %s MGR_UNREGLAYER | REQUEST\n", __FUNCTION__);
MGR_DISCONNECT | REQUEST, hw_mISDNObj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
&inst->up);
hw_mISDNObj.ctrl(inst, MGR_UNREGLAYER | REQUEST,
NULL);
break; break;
case MGR_CLRSTPARA | INDICATION: case MGR_CLRSTPARA | INDICATION:
arg = NULL; arg = NULL;
@ -481,40 +466,18 @@ hfcsusb_manager(void *data, u_int prim, void *arg)
} }
*/ */
break; break;
case MGR_CONNECT | REQUEST:
return (mISDN_ConnectIF(inst, arg));
case MGR_SETIF | REQUEST:
case MGR_SETIF | INDICATION:
if (channel == 2)
return (mISDN_SetIF
(inst, arg, prim, hfcsusb_l1hwD,
NULL, &card->dch));
else
return (mISDN_SetIF
(inst, arg, prim, hfcsusb_l2l1B,
NULL, &card->bch[channel]));
break;
case MGR_DISCONNECT | REQUEST:
case MGR_DISCONNECT | INDICATION:
return (mISDN_DisConnectIF(inst, arg));
case MGR_SETSTACK | INDICATION: case MGR_SETSTACK | INDICATION:
if ((channel != 2) && (inst->pid.global == 2)) { if ((channel != 2) && (inst->pid.global == 2)) {
inst->down.fdata = &card->bch[channel]; 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 (hfcsusb_l2l1B if (hfcsusb_l2l1B(inst, skb))
(&inst->down, skb))
dev_kfree_skb(skb); dev_kfree_skb(skb);
} }
if (inst->pid.protocol[2] == if (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS)
ISDN_PID_L2_B_TRANS) mISDN_queue_data(inst, FLG_MSG_UP, DL_ESTABLISH | INDICATION,
if_link(&inst->up,
DL_ESTABLISH | INDICATION,
0, 0, NULL, 0); 0, 0, NULL, 0);
else else
if_link(&inst->up, mISDN_queue_data(inst, FLG_MSG_UP, PH_ACTIVATE | INDICATION,
PH_ACTIVATE | INDICATION,
0, 0, NULL, 0); 0, 0, NULL, 0);
} }
break; break;
@ -547,11 +510,7 @@ S0_new_state(dchannel_t * dch)
{ {
u_int prim = PH_SIGNAL | INDICATION; u_int prim = PH_SIGNAL | INDICATION;
u_int para = 0; u_int para = 0;
mISDNif_t *upif = &dch->inst.up; hfcsusb_t *card = dch->inst.privat;
hfcsusb_t *card = dch->hw;
if (!test_and_clear_bit(D_L1STATECHANGE, &dch->event))
return;
if (card->hw_mode & HW_MODE_TE) { if (card->hw_mode & HW_MODE_TE) {
if (dch->debug) if (dch->debug)
@ -589,7 +548,7 @@ S0_new_state(dchannel_t * dch)
"%s: NT %d", "%s: NT %d",
__FUNCTION__, dch->ph_state); __FUNCTION__, dch->ph_state);
dch->inst.lock(dch->inst.data, 0); dch->inst.lock(dch->inst.privat, 0);
switch (dch->ph_state) { switch (dch->ph_state) {
case (1): case (1):
card->nt_timer = 0; card->nt_timer = 0;
@ -610,8 +569,8 @@ S0_new_state(dchannel_t * dch)
/* allow G2 -> G3 transition */ /* allow G2 -> G3 transition */
queued_Write_hfc(card, HFCUSB_STATES, 2 | HFCUSB_NT_G2_G3); queued_Write_hfc(card, HFCUSB_STATES, 2 | HFCUSB_NT_G2_G3);
} }
upif = NULL; dch->inst.unlock(dch->inst.privat);
break; return;
case (3): case (3):
card->nt_timer = 0; card->nt_timer = 0;
card->hw_mode &= ~NT_ACTIVATION_TIMER; card->hw_mode &= ~NT_ACTIVATION_TIMER;
@ -622,18 +581,14 @@ S0_new_state(dchannel_t * dch)
case (4): case (4):
card->nt_timer = 0; card->nt_timer = 0;
card->hw_mode &= ~NT_ACTIVATION_TIMER; card->hw_mode &= ~NT_ACTIVATION_TIMER;
upif = NULL; dch->inst.unlock(dch->inst.privat);
break; return;
default: default:
break; break;
} }
dch->inst.unlock(dch->inst.data); dch->inst.unlock(dch->inst.privat);
}
while (upif) {
if_link(upif, prim, para, 0, NULL, 0);
upif = upif->clone;
} }
mISDN_queue_data(&dch->inst, FLG_MSG_UP, prim, para, 0, NULL, 0);
} }
/******************************/ /******************************/
@ -647,7 +602,7 @@ state_handler(hfcsusb_t * card, __u8 new_l1_state)
return; return;
card->dch.ph_state = new_l1_state; card->dch.ph_state = new_l1_state;
dchannel_sched_event(&card->dch, D_L1STATECHANGE); S0_new_state(&card->dch);
} }
/* /*
@ -668,7 +623,7 @@ mode_bchannel(bchannel_t * bch, int bc, int protocol)
{ {
__u8 conhdlc, sctrl, sctrl_r; /* conatainer for new register vals */ __u8 conhdlc, sctrl, sctrl_r; /* conatainer for new register vals */
hfcsusb_t *card = bch->inst.data; hfcsusb_t *card = bch->inst.privat;
if (bch->debug & L1_DEB_HSCX) if (bch->debug & L1_DEB_HSCX)
mISDN_debugprint(&bch->inst, mISDN_debugprint(&bch->inst,
@ -744,10 +699,6 @@ mode_bchannel(bchannel_t * bch, int bc, int protocol)
if (protocol > ISDN_PID_NONE) { if (protocol > ISDN_PID_NONE) {
handle_led(card, ((bch->channel)?LED_B2_ON:LED_B1_ON)); handle_led(card, ((bch->channel)?LED_B2_ON:LED_B1_ON));
/* signal the channel has space for transmit data */
bch_sched_event(bch, B_XMTBUFREADY);
} else { } else {
handle_led(card, ((bch->channel)?LED_B2_OFF:LED_B1_OFF)); handle_led(card, ((bch->channel)?LED_B2_OFF:LED_B1_OFF));
} }
@ -814,19 +765,16 @@ hfcsusb_ph_command(hfcsusb_t * card, u_char command)
/* Layer 1 D-channel hardware access */ /* Layer 1 D-channel hardware access */
/*************************************/ /*************************************/
static int static int
hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb) hfcsusb_l1hwD(mISDNinstance_t *inst, struct sk_buff *skb)
{ {
dchannel_t *dch;; dchannel_t *dch;
int ret = -EINVAL; int ret = 0;
mISDN_head_t *hh; mISDN_head_t *hh;
hfcsusb_t *card; hfcsusb_t *card;
if (!hif || !skb)
return (ret);
hh = mISDN_HEAD_P(skb); hh = mISDN_HEAD_P(skb);
dch = hif->fdata; dch = container_of(inst, dchannel_t, inst);
card = dch->hw; card = inst->privat;
ret = 0;
if (hh->prim == PH_DATA_REQ) { if (hh->prim == PH_DATA_REQ) {
if (dch->next_skb) { if (dch->next_skb) {
@ -834,11 +782,11 @@ hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb)
"hfcsusb l2l1 next_skb exist this shouldn't happen"); "hfcsusb l2l1 next_skb exist this shouldn't happen");
return (-EBUSY); return (-EBUSY);
} }
dch->inst.lock(dch->inst.data, 0); dch->inst.lock(dch->inst.privat, 0);
if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) { if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) {
test_and_set_bit(FLG_TX_NEXT, &dch->DFlags); test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
dch->next_skb = skb; dch->next_skb = skb;
dch->inst.unlock(dch->inst.data); dch->inst.unlock(dch->inst.privat);
return (0); return (0);
} else { } else {
/* prepare buffer, which is transmitted by /* prepare buffer, which is transmitted by
@ -846,22 +794,23 @@ hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb)
dch->tx_len = skb->len; dch->tx_len = skb->len;
memcpy(dch->tx_buf, skb->data, dch->tx_len); memcpy(dch->tx_buf, skb->data, dch->tx_len);
dch->tx_idx = 0; dch->tx_idx = 0;
dch->inst.unlock(dch->inst.data); dch->inst.unlock(dch->inst.privat);
skb_trim(skb, 0); skb_trim(skb, 0);
return (if_newhead(&dch->inst.up, PH_DATA_CNF, return(mISDN_queueup_newhead(inst, 0, PH_DATA_CNF,
hh->dinfo, skb)); hh->dinfo, skb));
} }
} else if (hh->prim == (PH_SIGNAL | REQUEST)) { } else if (hh->prim == (PH_SIGNAL | REQUEST)) {
dch->inst.lock(dch->inst.data, 0); dch->inst.lock(dch->inst.privat, 0);
if (hh->dinfo == INFO3_P8) if (hh->dinfo == INFO3_P8)
hfcsusb_ph_command(dch->hw, S0_L1CMD_AR8); hfcsusb_ph_command(dch->hw, S0_L1CMD_AR8);
else if (hh->dinfo == INFO3_P10) else if (hh->dinfo == INFO3_P10)
hfcsusb_ph_command(dch->hw, S0_L1CMD_AR10); hfcsusb_ph_command(dch->hw, S0_L1CMD_AR10);
else else
ret = -EINVAL; ret = -EINVAL;
dch->inst.unlock(dch->inst.data);
dch->inst.unlock(dch->inst.privat);
} else if (hh->prim == (PH_CONTROL | REQUEST)) { } else if (hh->prim == (PH_CONTROL | REQUEST)) {
dch->inst.lock(dch->inst.data, 0); dch->inst.lock(dch->inst.privat, 0);
if (hh->dinfo == HW_RESET) { if (hh->dinfo == HW_RESET) {
if (dch->ph_state != 0) if (dch->ph_state != 0)
hfcsusb_ph_command(dch->hw, hfcsusb_ph_command(dch->hw,
@ -870,15 +819,16 @@ hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb)
} else if (hh->dinfo == HW_POWERUP) { } else if (hh->dinfo == HW_POWERUP) {
hfcsusb_ph_command(dch->hw, S0_L1CMD_ECK); hfcsusb_ph_command(dch->hw, S0_L1CMD_ECK);
} else if (hh->dinfo == HW_DEACTIVATE) { } else if (hh->dinfo == HW_DEACTIVATE) {
discard_queue(&dch->rqueue);
if (dch->next_skb) { if (dch->next_skb) {
dev_kfree_skb(dch->next_skb); dev_kfree_skb(dch->next_skb);
dch->next_skb = NULL; dch->next_skb = NULL;
} }
test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags); test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags); test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
#ifdef FIXME
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags)) if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
dchannel_sched_event(dch, D_CLEARBUSY); dchannel_sched_event(dch, D_CLEARBUSY);
#endif
} else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) { } else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) {
u_char val = 0; u_char val = 0;
@ -894,9 +844,9 @@ hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb)
hh->dinfo); hh->dinfo);
ret = -EINVAL; ret = -EINVAL;
} }
dch->inst.unlock(dch->inst.data); dch->inst.unlock(dch->inst.privat);
} else if (hh->prim == (PH_ACTIVATE | REQUEST)) { } else if (hh->prim == (PH_ACTIVATE | REQUEST)) {
dch->inst.lock(dch->inst.data, 0); dch->inst.lock(dch->inst.privat, 0);
if (card->hw_mode & HW_MODE_NT) { if (card->hw_mode & HW_MODE_NT) {
hfcsusb_ph_command(dch->hw, HFC_L1_ACTIVATE_NT); hfcsusb_ph_command(dch->hw, HFC_L1_ACTIVATE_NT);
} else { } else {
@ -905,9 +855,9 @@ hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb)
__FUNCTION__); __FUNCTION__);
ret = -EINVAL; ret = -EINVAL;
} }
dch->inst.unlock(dch->inst.data); dch->inst.unlock(dch->inst.privat);
} else if (hh->prim == (PH_DEACTIVATE | REQUEST)) { } else if (hh->prim == (PH_DEACTIVATE | REQUEST)) {
dch->inst.lock(dch->inst.data, 0); dch->inst.lock(dch->inst.privat, 0);
if (card->hw_mode & HW_MODE_NT) { if (card->hw_mode & HW_MODE_NT) {
hfcsusb_ph_command(dch->hw, HFC_L1_DEACTIVATE_NT); hfcsusb_ph_command(dch->hw, HFC_L1_DEACTIVATE_NT);
} else { } else {
@ -916,7 +866,7 @@ hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb)
__FUNCTION__); __FUNCTION__);
ret = -EINVAL; ret = -EINVAL;
} }
dch->inst.unlock(dch->inst.data); dch->inst.unlock(dch->inst.privat);
} else { } else {
if (dch->debug & L1_DEB_WARN) if (dch->debug & L1_DEB_WARN)
mISDN_debugprint(&dch->inst, mISDN_debugprint(&dch->inst,
@ -933,20 +883,11 @@ hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb)
/* Layer2 -> Layer 1 Transfer */ /* Layer2 -> Layer 1 Transfer */
/******************************/ /******************************/
static int static int
hfcsusb_l2l1B(mISDNif_t * hif, struct sk_buff *skb) hfcsusb_l2l1B(mISDNinstance_t *inst, struct sk_buff *skb)
{ {
bchannel_t *bch; bchannel_t *bch = container_of(inst, bchannel_t, inst);
int ret = -EINVAL; int ret = 0;
mISDN_head_t *hh; mISDN_head_t *hh = mISDN_HEAD_P(skb);
hfcsusb_t *card;
if (!hif || !skb)
return (ret);
hh = mISDN_HEAD_P(skb);
bch = hif->fdata;
card = bch->hw;
if ((hh->prim == PH_DATA_REQ) || (hh->prim == (DL_DATA | REQUEST))) { if ((hh->prim == PH_DATA_REQ) || (hh->prim == (DL_DATA | REQUEST))) {
if (bch->next_skb) { if (bch->next_skb) {
@ -954,11 +895,13 @@ hfcsusb_l2l1B(mISDNif_t * hif, struct sk_buff *skb)
__FUNCTION__); __FUNCTION__);
return (-EBUSY); return (-EBUSY);
} }
bch->inst.lock(bch->inst.data, 0); if (skb->len <= 0)
return(-EINVAL);
bch->inst.lock(bch->inst.privat, 0);
if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) { if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag); test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
bch->next_skb = skb; bch->next_skb = skb;
bch->inst.unlock(bch->inst.data); bch->inst.unlock(bch->inst.privat);
return (0); return (0);
} else { } else {
/* prepare buffer, wich is transmitted by /* prepare buffer, wich is transmitted by
@ -966,40 +909,39 @@ hfcsusb_l2l1B(mISDNif_t * hif, struct sk_buff *skb)
bch->tx_len = skb->len; bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len); memcpy(bch->tx_buf, skb->data, bch->tx_len);
bch->tx_idx = 0; bch->tx_idx = 0;
bch->inst.unlock(bch->inst.data); bch->inst.unlock(bch->inst.privat);
if ((bch->inst.pid.protocol[2] == #ifdef FIXME
ISDN_PID_L2_B_RAWDEV) if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
&& bch->dev) && bch->dev)
hif = &bch->dev->rport.pif; hif = &bch->dev->rport.pif;
else else
hif = &bch->inst.up; hif = &bch->inst.up;
#endif
skb_trim(skb, 0); skb_trim(skb, 0);
return (if_newhead(hif, hh->prim | CONFIRM, return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM,
hh->dinfo, skb)); hh->dinfo, skb));
} }
} else if ((hh->prim == (PH_ACTIVATE | REQUEST)) || } 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(BC_FLG_ACTIV, &bch->Flag)) {
ret = 0; bch->inst.lock(bch->inst.privat, 0);
else { ret = mode_bchannel(bch, bch->channel,
bch->inst.lock(bch->inst.data, 0);
ret =
mode_bchannel(bch, bch->channel,
bch->inst.pid.protocol[1]); bch->inst.pid.protocol[1]);
bch->inst.unlock(bch->inst.data); bch->inst.unlock(bch->inst.privat);
} }
#ifdef FIXME
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV) if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
if (bch->dev) if (bch->dev)
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
skb_trim(skb, 0); skb_trim(skb, 0);
return (if_newhead return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, ret, skb));
(&bch->inst.up, 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 == (MGR_DISCONNECT | REQUEST))) {
bch->inst.lock(bch->inst.data, 0); bch->inst.lock(bch->inst.privat, 0);
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) { if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
dev_kfree_skb(bch->next_skb); dev_kfree_skb(bch->next_skb);
bch->next_skb = NULL; bch->next_skb = NULL;
@ -1007,26 +949,25 @@ hfcsusb_l2l1B(mISDNif_t * hif, struct sk_buff *skb)
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag); test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
mode_bchannel(bch, bch->channel, ISDN_PID_NONE); mode_bchannel(bch, bch->channel, ISDN_PID_NONE);
test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag); test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag);
bch->inst.unlock(bch->inst.data); bch->inst.unlock(bch->inst.privat);
skb_trim(skb, 0); skb_trim(skb, 0);
if (hh->prim != (MGR_DISCONNECT | REQUEST)) { if (hh->prim != (PH_CONTROL | REQUEST)) {
if (bch->inst.pid.protocol[2] == #ifdef FIXME
ISDN_PID_L2_B_RAWDEV) if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
if (bch->dev) if (bch->dev)
if_link(&bch->dev->rport.pif, if_link(&bch->dev->rport.pif,
hh->prim | CONFIRM, 0, 0, hh->prim | CONFIRM, 0, 0, NULL, 0);
NULL, 0); #endif
if (!if_newhead if (!mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, 0, skb))
(&bch->inst.up, hh->prim | CONFIRM, 0, skb))
return(0); return(0);
} }
ret = 0;
} else if (hh->prim == (PH_CONTROL | REQUEST)) { } else if (hh->prim == (PH_CONTROL | REQUEST)) {
// do not handle PH_CONTROL | REQUEST ?? // do not handle PH_CONTROL | REQUEST ??
ret = -EINVAL;
} else { } else {
printk(KERN_WARNING "%s: unknown prim(%x)\n", printk(KERN_WARNING "%s: unknown prim(%x)\n",
__FUNCTION__, hh->prim); __FUNCTION__, hh->prim);
ret = -EINVAL;
} }
if (!ret) if (!ret)
dev_kfree_skb(skb); dev_kfree_skb(skb);
@ -1083,23 +1024,15 @@ collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish)
if (card->bch[fifo->bch_idx].protocol == ISDN_PID_L1_B_64TRANS) { if (card->bch[fifo->bch_idx].protocol == ISDN_PID_L1_B_64TRANS) {
if (fifo->skbuff->len >= 128) { if (fifo->skbuff->len >= 128) {
if (!(skb = alloc_stack_skb(fifo->skbuff->len, if (!(skb = alloc_stack_skb(fifo->skbuff->len,
card->bch->up_headerlen))) card->bch[fifo->bch_idx].up_headerlen)))
printk(KERN_WARNING "HFC-S USB: receive out of memory\n"); printk(KERN_WARNING "HFC-S USB: receive out of memory\n");
else { else {
ptr = ptr = skb_put(skb, fifo->skbuff->len);
skb_put(skb, memcpy(ptr, fifo->skbuff->data, fifo->skbuff->len);
fifo->skbuff->
len);
memcpy(ptr, fifo->skbuff->data,
fifo->skbuff->len);
dev_kfree_skb(fifo->skbuff); dev_kfree_skb(fifo->skbuff);
fifo->skbuff=NULL; fifo->skbuff=NULL;
queue_bch_frame(&card->bch[fifo->bch_idx],
skb_queue_tail(&card->bch[fifo->bch_idx]. INDICATION, MISDN_ID_ANY, skb);
rqueue,
skb);
bch_sched_event(&card->bch[fifo->bch_idx], B_RCVBUFREADY);
} }
} }
return; return;
@ -1115,28 +1048,15 @@ collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish)
switch (fifon) { switch (fifon) {
case HFCUSB_D_RX: case HFCUSB_D_RX:
if ((skb = if ((skb = alloc_stack_skb(fifo->skbuff->len,
alloc_stack_skb(fifo->skbuff-> card->dch.up_headerlen))) {
len, ptr = skb_put(skb, fifo->skbuff->len);
card->dch. memcpy(ptr, fifo->skbuff->data,
up_headerlen))) fifo->skbuff->len);
{
ptr =
skb_put(skb,
fifo->skbuff->
len);
memcpy(ptr, fifo->skbuff->data, fifo->skbuff->len);
dev_kfree_skb(fifo->skbuff); dev_kfree_skb(fifo->skbuff);
fifo->skbuff=NULL; fifo->skbuff=NULL;
mISDN_queueup_newhead(&card->dch.inst, 0,
skb_queue_tail(&card->dch. PH_DATA_IND, MISDN_ID_ANY, skb);
rqueue,
skb);
dchannel_sched_event
(&card->dch,
D_RCVBUFREADY);
} else { } else {
printk(KERN_WARNING printk(KERN_WARNING
"HFC-S USB: D receive out of memory\n"); "HFC-S USB: D receive out of memory\n");
@ -1145,30 +1065,15 @@ collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish)
case HFCUSB_B1_RX: case HFCUSB_B1_RX:
case HFCUSB_B2_RX: case HFCUSB_B2_RX:
if (card->bch[fifo->bch_idx].protocol > ISDN_PID_NONE) { if (card->bch[fifo->bch_idx].protocol > ISDN_PID_NONE) {
if ((skb = if ((skb = alloc_stack_skb(fifo->skbuff->len,
alloc_stack_skb(fifo->skbuff-> card->bch[fifo->bch_idx].up_headerlen)))
len,
card->
bch[fifo->bch_idx].
up_headerlen)))
{ {
ptr = ptr = skb_put(skb, fifo->skbuff->len);
skb_put(skb,
fifo->skbuff->
len);
memcpy(ptr, fifo->skbuff->data, fifo->skbuff->len); memcpy(ptr, fifo->skbuff->data, fifo->skbuff->len);
dev_kfree_skb(fifo->skbuff); dev_kfree_skb(fifo->skbuff);
fifo->skbuff=NULL; fifo->skbuff=NULL;
queue_bch_frame(&card->bch[fifo->bch_idx],
skb_queue_tail(&card-> INDICATION, MISDN_ID_ANY, skb);
bch
[fifo->bch_idx].
rqueue,
skb);
bch_sched_event(&card->
bch
[fifo->bch_idx],
B_RCVBUFREADY);
} else { } else {
printk(KERN_WARNING printk(KERN_WARNING
"HFC-S USB: B%i receive out of memory\n", "HFC-S USB: B%i receive out of memory\n",
@ -1372,16 +1277,22 @@ rx_int_complete(struct urb *urb, struct pt_regs *regs)
void void
next_d_tx_frame(hfcsusb_t * card) next_d_tx_frame(hfcsusb_t * card)
{ {
if (test_and_clear_bit(FLG_TX_NEXT, &card->dch.DFlags)) { if (test_bit(FLG_TX_NEXT, &card->dch.DFlags)) {
if (card->dch.next_skb) { struct sk_buff *skb = card->dch.next_skb;
card->dch.tx_len = card->dch.next_skb->len; if (skb) {
memcpy(card->dch.tx_buf, mISDN_head_t *hh = mISDN_HEAD_P(skb);
card->dch.next_skb->data, card->dch.tx_len);
card->dch.next_skb = NULL;
test_and_clear_bit(FLG_TX_NEXT, &card->dch.DFlags);
card->dch.tx_len = skb->len;
memcpy(card->dch.tx_buf, skb->data, card->dch.tx_len);
card->dch.tx_idx = 0; card->dch.tx_idx = 0;
dchannel_sched_event(&card->dch, D_XMTBUFREADY); if (mISDN_queueup_newhead(&card->dch.inst, 0, PH_DATA_CNF, hh->dinfo, skb))
dev_kfree_skb(skb);
} else { } else {
printk(KERN_WARNING printk(KERN_WARNING
"hfcd tx irq TX_NEXT without skb\n"); "hfcd tx irq TX_NEXT without skb\n");
test_and_clear_bit(FLG_TX_NEXT, &card->dch.DFlags);
test_and_clear_bit(FLG_TX_BUSY, &card->dch.DFlags); test_and_clear_bit(FLG_TX_BUSY, &card->dch.DFlags);
} }
} else } else
@ -1391,20 +1302,23 @@ next_d_tx_frame(hfcsusb_t * card)
void void
next_b_tx_frame(hfcsusb_t * card, __u8 bch_idx) next_b_tx_frame(hfcsusb_t * card, __u8 bch_idx)
{ {
if (test_and_clear_bit(BC_FLG_TX_NEXT, &card->bch[bch_idx].Flag)) { if (test_bit(BC_FLG_TX_NEXT, &card->bch[bch_idx].Flag)) {
if (card->bch[bch_idx].next_skb) { struct sk_buff *skb = card->bch[bch_idx].next_skb;
if (skb) {
mISDN_head_t *hh = mISDN_HEAD_P(skb);
card->bch[bch_idx].next_skb = NULL;
test_and_clear_bit(BC_FLG_TX_NEXT, &card->bch[bch_idx].Flag);
card->bch[bch_idx].tx_idx = 0; card->bch[bch_idx].tx_idx = 0;
card->bch[bch_idx].tx_len = card->bch[bch_idx].tx_len = skb->len;
card->bch[bch_idx].next_skb->len; memcpy(card->bch[bch_idx].tx_buf, skb->data, card->bch[bch_idx].tx_len);
memcpy(card->bch[bch_idx].tx_buf,
card->bch[bch_idx].next_skb->data, queue_bch_frame(&card->bch[bch_idx], CONFIRM, hh->dinfo, skb);
card->bch[bch_idx].tx_len); } else {
bch_sched_event(&card->bch[bch_idx],
B_XMTBUFREADY);
} else
printk(KERN_WARNING printk(KERN_WARNING
"hfc B%i tx irq TX_NEXT without skb\n", "hfc B%i tx irq TX_NEXT without skb\n", bch_idx);
bch_idx); test_and_clear_bit(BC_FLG_TX_NEXT, &card->bch[bch_idx].Flag);
}
} }
} }
@ -1572,7 +1486,7 @@ tx_iso_complete(struct urb *urb, struct pt_regs *regs)
if ((fifon == HFCUSB_D_TX) && (card->hw_mode & HW_MODE_NT) if ((fifon == HFCUSB_D_TX) && (card->hw_mode & HW_MODE_NT)
&& (card->hw_mode & NT_ACTIVATION_TIMER)) { && (card->hw_mode & NT_ACTIVATION_TIMER)) {
if ((--card->nt_timer) < 0) if ((--card->nt_timer) < 0)
dchannel_sched_event(&card->dch, D_L1STATECHANGE); S0_new_state(&card->dch);
} }
} else { } else {
@ -1882,8 +1796,6 @@ release_card(hfcsusb_t * card)
mISDN_free_bch(&card->bch[1]); mISDN_free_bch(&card->bch[1]);
mISDN_free_bch(&card->bch[0]); mISDN_free_bch(&card->bch[0]);
mISDN_free_dch(&card->dch); mISDN_free_dch(&card->dch);
hw_mISDNObj.ctrl(card->dch.inst.up.peer, MGR_DISCONNECT | REQUEST,
&card->dch.inst.up);
hw_mISDNObj.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL); hw_mISDNObj.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
list_del(&card->list); list_del(&card->list);
unlock_dev(card); unlock_dev(card);
@ -1934,7 +1846,7 @@ setup_instance(hfcsusb_t * card)
card->dch.inst.unlock = unlock_dev; card->dch.inst.unlock = unlock_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, &hw_mISDNObj, card); mISDN_init_instance(&card->dch.inst, &hw_mISDNObj, card, hfcsusb_l1hwD);
sprintf(card->dch.inst.name, "hfcsusb_%d", hfcsusb_cnt + 1); sprintf(card->dch.inst.name, "hfcsusb_%d", hfcsusb_cnt + 1);
mISDN_set_dchannel_pid(&pid, protocol[hfcsusb_cnt], mISDN_set_dchannel_pid(&pid, protocol[hfcsusb_cnt],
layermask[hfcsusb_cnt]); layermask[hfcsusb_cnt]);
@ -1944,8 +1856,7 @@ setup_instance(hfcsusb_t * 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, &hw_mISDNObj, mISDN_init_instance(&card->bch[i].inst, &hw_mISDNObj, card, hfcsusb_l2l1B);
card);
card->bch[i].inst.pid.layermask = ISDN_LAYER(0); card->bch[i].inst.pid.layermask = ISDN_LAYER(0);
card->bch[i].inst.lock = lock_dev; card->bch[i].inst.lock = lock_dev;
card->bch[i].inst.unlock = unlock_dev; card->bch[i].inst.unlock = unlock_dev;
@ -1954,10 +1865,12 @@ setup_instance(hfcsusb_t * card)
card->dch.inst.name, i + 1); card->dch.inst.name, i + 1);
mISDN_init_bch(&card->bch[i]); mISDN_init_bch(&card->bch[i]);
card->bch[i].hw = card; card->bch[i].hw = card;
#ifdef FIXME
if (card->bch[i].dev) { if (card->bch[i].dev) {
card->bch[i].dev->wport.pif.func = hfcsusb_l2l1B; card->bch[i].dev->wport.pif.func = hfcsusb_l2l1B;
card->bch[i].dev->wport.pif.fdata = &card->bch[i]; card->bch[i].dev->wport.pif.fdata = &card->bch[i];
} }
#endif
} }
if (protocol[hfcsusb_cnt] & 0x10) { if (protocol[hfcsusb_cnt] & 0x10) {

View File

@ -243,16 +243,16 @@ isac_xpr_irq(dchannel_t *dch)
if (dch->tx_idx < dch->tx_len) { if (dch->tx_idx < dch->tx_len) {
isac_fill_fifo(dch); isac_fill_fifo(dch);
} else { } else {
if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) { if (test_bit(FLG_TX_NEXT, &dch->DFlags)) {
struct sk_buff *skb; struct sk_buff *skb = dch->next_skb;
mISDN_head_t *hh; mISDN_head_t *hh = mISDN_HEAD_P(skb);
if ((skb = dch->next_skb)) { if (skb) {
dch->next_skb = NULL; dch->next_skb = NULL;
test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
dch->tx_len = skb->len; dch->tx_len = skb->len;
memcpy(dch->tx_buf, skb->data, dch->tx_len); memcpy(dch->tx_buf, skb->data, dch->tx_len);
dch->tx_idx = 0; dch->tx_idx = 0;
isac_fill_fifo(dch); isac_fill_fifo(dch);
hh = mISDN_HEAD_P(skb);
skb_trim(skb, 0); skb_trim(skb, 0);
if (unlikely(mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_CNF, hh->dinfo, skb))) { if (unlikely(mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_CNF, hh->dinfo, skb))) {
int_error(); int_error();
@ -260,6 +260,7 @@ isac_xpr_irq(dchannel_t *dch)
} }
} else { } else {
printk(KERN_WARNING "isac tx irq TX_NEXT without skb\n"); printk(KERN_WARNING "isac tx irq TX_NEXT without skb\n");
test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags); test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
} }
} else } else
@ -283,11 +284,12 @@ isac_retransmit(dchannel_t *dch)
} else { } else {
printk(KERN_WARNING "mISDN: ISAC XDU no TX_BUSY\n"); printk(KERN_WARNING "mISDN: ISAC XDU no TX_BUSY\n");
mISDN_debugprint(&dch->inst, "ISAC XDU no TX_BUSY"); mISDN_debugprint(&dch->inst, "ISAC XDU no TX_BUSY");
if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) { if (test_bit(FLG_TX_NEXT, &dch->DFlags)) {
struct sk_buff *skb; struct sk_buff *skb = dch->next_skb;
mISDN_head_t *hh; mISDN_head_t *hh = mISDN_HEAD_P(skb);
if ((skb = dch->next_skb)) { if (skb) {
dch->next_skb = NULL; dch->next_skb = NULL;
test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
dch->tx_len = skb->len; dch->tx_len = skb->len;
memcpy(dch->tx_buf, skb->data, dch->tx_len); memcpy(dch->tx_buf, skb->data, dch->tx_len);
dch->tx_idx = 0; dch->tx_idx = 0;
@ -300,6 +302,7 @@ isac_retransmit(dchannel_t *dch)
} }
} else { } else {
printk(KERN_WARNING "isac xdu irq TX_NEXT without skb\n"); printk(KERN_WARNING "isac xdu irq TX_NEXT without skb\n");
test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
} }
} }
} }

View File

@ -10,7 +10,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include "layer1.h" #include "layer1.h"
#include "helper.h"
#include "bchannel.h" #include "bchannel.h"
#include "isar.h" #include "isar.h"
#include "debug.h" #include "debug.h"
@ -462,7 +461,6 @@ isar_rcv_frame(bchannel_t *bch)
{ {
u_char *ptr; u_char *ptr;
struct sk_buff *skb; struct sk_buff *skb;
u_int pr;
isar_hw_t *ih = bch->hw; isar_hw_t *ih = bch->hw;
if (!ih->reg->clsb) { if (!ih->reg->clsb) {
@ -483,14 +481,7 @@ isar_rcv_frame(bchannel_t *bch)
case ISDN_PID_L1_B_MODEM_ASYNC: case ISDN_PID_L1_B_MODEM_ASYNC:
if ((skb = alloc_stack_skb(ih->reg->clsb, bch->up_headerlen))) { if ((skb = alloc_stack_skb(ih->reg->clsb, bch->up_headerlen))) {
rcv_mbox(bch, ih->reg, (u_char *)skb_put(skb, ih->reg->clsb)); rcv_mbox(bch, ih->reg, (u_char *)skb_put(skb, ih->reg->clsb));
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS) queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
pr = DL_DATA | INDICATION;
else
pr = PH_DATA | INDICATION;
if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, MISDN_ID_ANY, skb))) {
int_error();
dev_kfree_skb(skb);
}
} else { } else {
printk(KERN_WARNING "mISDN: skb out of memory\n"); printk(KERN_WARNING "mISDN: skb out of memory\n");
bch->Write_Reg(bch->inst.privat, 1, ISAR_IIA, 0); bch->Write_Reg(bch->inst.privat, 1, ISAR_IIA, 0);
@ -530,14 +521,7 @@ isar_rcv_frame(bchannel_t *bch)
} else { } else {
memcpy(skb_put(skb, bch->rx_idx-2), memcpy(skb_put(skb, bch->rx_idx-2),
bch->rx_buf, bch->rx_idx-2); bch->rx_buf, bch->rx_idx-2);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS) queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
pr = DL_DATA | INDICATION;
else
pr = PH_DATA | INDICATION;
if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, MISDN_ID_ANY, skb))) {
int_error();
dev_kfree_skb(skb);
}
} }
bch->rx_idx = 0; bch->rx_idx = 0;
} }
@ -569,14 +553,7 @@ isar_rcv_frame(bchannel_t *bch)
ih->state = STFAX_ESCAPE; ih->state = STFAX_ESCAPE;
// set_skb_flag(skb, DF_NOMOREDATA); // set_skb_flag(skb, DF_NOMOREDATA);
} }
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS) queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
pr = DL_DATA | INDICATION;
else
pr = PH_DATA | INDICATION;
if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, MISDN_ID_ANY, skb))) {
int_error();
dev_kfree_skb(skb);
}
if (ih->reg->cmsb & SART_NMD) if (ih->reg->cmsb & SART_NMD)
deliver_status(bch, HW_MOD_NOCARR); deliver_status(bch, HW_MOD_NOCARR);
} else { } else {
@ -623,14 +600,7 @@ isar_rcv_frame(bchannel_t *bch)
// if (ih->reg->cmsb & SART_NMD) // if (ih->reg->cmsb & SART_NMD)
/* ABORT */ /* ABORT */
// set_skb_flag(skb, DF_NOMOREDATA); // set_skb_flag(skb, DF_NOMOREDATA);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS) queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
pr = DL_DATA | INDICATION;
else
pr = PH_DATA | INDICATION;
if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, MISDN_ID_ANY, skb))) {
int_error();
dev_kfree_skb(skb);
}
} }
bch->rx_idx = 0; bch->rx_idx = 0;
} }
@ -772,29 +742,23 @@ send_frames(bchannel_t *bch)
} }
} }
} }
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) { if (test_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
struct sk_buff *skb = bch->next_skb; struct sk_buff *skb = bch->next_skb;
mISDN_head_t *hh; mISDN_head_t *hh;
u_int pr;
if (skb) { if (skb) {
bch->next_skb = NULL; bch->next_skb = NULL;
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
hh = mISDN_HEAD_P(skb); hh = mISDN_HEAD_P(skb);
bch->tx_idx = 0; bch->tx_idx = 0;
bch->tx_len = skb->len; bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len); memcpy(bch->tx_buf, skb->data, bch->tx_len);
isar_fill_fifo(bch); isar_fill_fifo(bch);
skb_trim(skb, 0); skb_trim(skb, 0);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS) queue_bch_frame(bch, CONFIRM, hh->dinfo, skb);
pr = DL_DATA | CONFIRM;
else
pr = PH_DATA | CONFIRM;
if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, hh->dinfo, skb))) {
int_error();
dev_kfree_skb(skb);
}
} else { } else {
bch->tx_len = 0; bch->tx_len = 0;
printk(KERN_WARNING "isar tx irq TX_NEXT without skb\n"); printk(KERN_WARNING "isar tx irq TX_NEXT without skb\n");
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag); test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
} }
} else { } else {
@ -1597,18 +1561,19 @@ int
isar_down(mISDNinstance_t *inst, struct sk_buff *skb) isar_down(mISDNinstance_t *inst, struct sk_buff *skb)
{ {
bchannel_t *bch; bchannel_t *bch;
int ret = -EINVAL; int ret = 0;
mISDN_head_t *hh; mISDN_head_t *hh;
hh = mISDN_HEAD_P(skb); hh = mISDN_HEAD_P(skb);
bch = container_of(inst, bchannel_t, inst); bch = container_of(inst, bchannel_t, inst);
ret = 0;
if ((hh->prim == PH_DATA_REQ) || if ((hh->prim == PH_DATA_REQ) ||
(hh->prim == (DL_DATA | REQUEST))) { (hh->prim == (DL_DATA | REQUEST))) {
if (bch->next_skb) { if (bch->next_skb) {
mISDN_debugprint(&bch->inst, " l2l1 next_skb exist this shouldn't happen"); mISDN_debugprint(&bch->inst, " l2l1 next_skb exist this shouldn't happen");
return(-EBUSY); return(-EBUSY);
} }
if (skb->len <= 0)
return(-EINVAL);
bch->inst.lock(bch->inst.privat, 0); bch->inst.lock(bch->inst.privat, 0);
if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) { if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag); test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
@ -1627,9 +1592,7 @@ isar_down(mISDNinstance_t *inst, struct sk_buff *skb)
} }
} else if ((hh->prim == (PH_ACTIVATE | REQUEST)) || } 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(BC_FLG_ACTIV, &bch->Flag)) {
ret = 0;
else {
u_int bp = bch->inst.pid.protocol[1]; u_int bp = bch->inst.pid.protocol[1];
if (bch->inst.pid.global == 1) if (bch->inst.pid.global == 1)
@ -1657,8 +1620,7 @@ isar_down(mISDNinstance_t *inst, struct sk_buff *skb)
bch->inst.unlock(bch->inst.privat); bch->inst.unlock(bch->inst.privat);
skb_trim(skb, 0); skb_trim(skb, 0);
if (hh->prim != (PH_CONTROL | REQUEST)) if (hh->prim != (PH_CONTROL | REQUEST))
if (!mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, 0, skb)) ret = mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, 0, skb);
return(0);
} else if (hh->prim == (PH_CONTROL | REQUEST)) { } else if (hh->prim == (PH_CONTROL | REQUEST)) {
int *val; int *val;
int len; int len;
@ -1704,6 +1666,7 @@ isar_down(mISDNinstance_t *inst, struct sk_buff *skb)
int_errtxt("wrong modulation"); int_errtxt("wrong modulation");
/* wrong modulation or not activ */ /* wrong modulation or not activ */
// TODO // TODO
ret = -EINVAL;
} }
} else if (hh->dinfo == HW_MOD_LASTDATA) { } else if (hh->dinfo == HW_MOD_LASTDATA) {
test_and_set_bit(BC_FLG_DLEETX, &bch->Flag); test_and_set_bit(BC_FLG_DLEETX, &bch->Flag);

View File

@ -149,24 +149,13 @@ W6692_new_ph(dchannel_t *dch)
{ {
u_int prim = PH_SIGNAL | INDICATION; u_int prim = PH_SIGNAL | INDICATION;
u_int para = 0; u_int para = 0;
mISDNif_t *upif = &dch->inst.up;
if (dch->debug)
printk(KERN_DEBUG "%s: event %lx\n", __FUNCTION__, dch->event);
if (!test_and_clear_bit(D_L1STATECHANGE, &dch->event))
return;
switch (dch->ph_state) { switch (dch->ph_state) {
case W_L1CMD_RST: case W_L1CMD_RST:
dch->inst.lock(dch->inst.data, 0); dch->inst.lock(dch->inst.privat, 0);
ph_command(dch->hw, W_L1CMD_DRC); ph_command(dch->hw, W_L1CMD_DRC);
dch->inst.unlock(dch->inst.data); dch->inst.unlock(dch->inst.privat);
prim = PH_CONTROL | INDICATION; mISDN_queue_data(&dch->inst, FLG_MSG_UP, PH_CONTROL | INDICATION, HW_RESET, 0, NULL, 0);
para = HW_RESET;
while(upif) {
if_link(upif, prim, para, 0, NULL, 0);
upif = upif->clone;
}
upif = &dch->inst.up;
/* fall trough */ /* fall trough */
case W_L1IND_CD: case W_L1IND_CD:
prim = PH_CONTROL | CONFIRM; prim = PH_CONTROL | CONFIRM;
@ -195,10 +184,7 @@ W6692_new_ph(dchannel_t *dch)
default: default:
return; return;
} }
while(upif) { mISDN_queue_data(&dch->inst, FLG_MSG_UP, prim, para, 0, NULL, 0);
if_link(upif, prim, para, 0, NULL, 0);
upif = upif->clone;
}
} }
static void static void
@ -281,8 +267,10 @@ d_retransmit(w6692pci *card)
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags)) if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
del_timer(&dch->dbusytimer); del_timer(&dch->dbusytimer);
#ifdef FIXME
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags)) if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
dchannel_sched_event(dch, D_CLEARBUSY); dchannel_sched_event(dch, D_CLEARBUSY);
#endif
if (test_bit(FLG_TX_BUSY, &dch->DFlags)) { if (test_bit(FLG_TX_BUSY, &dch->DFlags)) {
/* Restart frame */ /* Restart frame */
dch->tx_idx = 0; dch->tx_idx = 0;
@ -290,17 +278,22 @@ d_retransmit(w6692pci *card)
} else { } else {
printk(KERN_WARNING "mISDN: w6692 XDU no TX_BUSY\n"); printk(KERN_WARNING "mISDN: w6692 XDU no TX_BUSY\n");
mISDN_debugprint(&dch->inst, "XDU no TX_BUSY"); mISDN_debugprint(&dch->inst, "XDU no TX_BUSY");
if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) { if (test_bit(FLG_TX_NEXT, &dch->DFlags)) {
if (dch->next_skb) { struct sk_buff *skb = dch->next_skb;
dch->tx_len = dch->next_skb->len; if (skb) {
memcpy(dch->tx_buf, mISDN_head_t *hh = mISDN_HEAD_P(skb);
dch->next_skb->data, dch->next_skb = NULL;
dch->tx_len); test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
dch->tx_len = skb->len;
memcpy(dch->tx_buf, skb->data, dch->tx_len);
dch->tx_idx = 0; dch->tx_idx = 0;
W6692_fill_Dfifo(card); W6692_fill_Dfifo(card);
dchannel_sched_event(dch, D_XMTBUFREADY); skb_trim(skb, 0);
if (mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_CNF, hh->dinfo, skb))
dev_kfree_skb(skb);
} else { } else {
printk(KERN_WARNING "w6692 xdu irq TX_NEXT without skb\n"); printk(KERN_WARNING "w6692 xdu irq TX_NEXT without skb\n");
test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
} }
} }
} }
@ -342,12 +335,11 @@ handle_rxD(w6692pci *card) {
if (count == 0) if (count == 0)
count = W_D_FIFO_THRESH; count = W_D_FIFO_THRESH;
W6692_empty_Dfifo(card, count); W6692_empty_Dfifo(card, count);
if (card->dch.rx_skb) { if (card->dch.rx_skb)
skb_queue_tail(&card->dch.rqueue, card->dch.rx_skb); mISDN_queueup_newhead(&card->dch.inst, 0, PH_DATA_IND,
} MISDN_ID_ANY, card->dch.rx_skb);
} }
card->dch.rx_skb = NULL; card->dch.rx_skb = NULL;
dchannel_sched_event(&card->dch, D_RCVBUFREADY);
} }
static void static void
@ -356,21 +348,29 @@ handle_txD(w6692pci *card) {
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags)) if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
del_timer(&dch->dbusytimer); del_timer(&dch->dbusytimer);
#ifdef FIXME
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags)) if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
dchannel_sched_event(dch, D_CLEARBUSY); dchannel_sched_event(dch, D_CLEARBUSY);
#endif
if (dch->tx_idx < dch->tx_len) { if (dch->tx_idx < dch->tx_len) {
W6692_fill_Dfifo(card); W6692_fill_Dfifo(card);
} else { } else {
if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) { if (test_bit(FLG_TX_NEXT, &dch->DFlags)) {
if (dch->next_skb) { struct sk_buff *skb = dch->next_skb;
dch->tx_len = dch->next_skb->len; if (skb) {
memcpy(dch->tx_buf, mISDN_head_t *hh = mISDN_HEAD_P(skb);
dch->next_skb->data, dch->tx_len); dch->next_skb = NULL;
test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
dch->tx_len = skb->len;
memcpy(dch->tx_buf, skb->data, dch->tx_len);
dch->tx_idx = 0; dch->tx_idx = 0;
W6692_fill_Dfifo(card); W6692_fill_Dfifo(card);
dchannel_sched_event(dch, D_XMTBUFREADY); skb_trim(skb, 0);
if (mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_CNF, hh->dinfo, skb))
dev_kfree_skb(skb);
} else { } else {
printk(KERN_WARNING "w6692 txD irq TX_NEXT without skb\n"); printk(KERN_WARNING "w6692 txD irq TX_NEXT without skb\n");
test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags); test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
} }
} else } else
@ -431,7 +431,7 @@ handle_statusD(w6692pci *card) {
break; break;
} }
} }
dchannel_sched_event(dch, D_L1STATECHANGE); W6692_new_ph(dch);
} }
if (cir & W_CIR_SCC) { if (cir & W_CIR_SCC) {
v1 = ReadW6692(card, W_SQR); v1 = ReadW6692(card, W_SQR);
@ -453,7 +453,7 @@ static void
W6692_empty_Bfifo(bchannel_t *bch, int count) W6692_empty_Bfifo(bchannel_t *bch, int count)
{ {
u_char *ptr; u_char *ptr;
w6692pci *card = bch->inst.data; 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);
@ -488,7 +488,7 @@ W6692_empty_Bfifo(bchannel_t *bch, int count)
static void static void
W6692_fill_Bfifo(bchannel_t *bch) W6692_fill_Bfifo(bchannel_t *bch)
{ {
w6692pci *card = bch->inst.data; w6692pci *card = bch->inst.privat;
int count; int count;
u_char *ptr, cmd = W_B_CMDR_RACT | W_B_CMDR_XMS; u_char *ptr, cmd = W_B_CMDR_RACT | W_B_CMDR_XMS;
@ -523,7 +523,7 @@ W6692_fill_Bfifo(bchannel_t *bch)
static int static int
setvolume(bchannel_t *bch, int mic, struct sk_buff *skb) setvolume(bchannel_t *bch, int mic, struct sk_buff *skb)
{ {
w6692pci *card = bch->inst.data; w6692pci *card = bch->inst.privat;
u16 *vol = (u16 *)skb->data; u16 *vol = (u16 *)skb->data;
u_char val; u_char val;
@ -550,7 +550,7 @@ static int
enable_pots(bchannel_t *bch) enable_pots(bchannel_t *bch)
{ {
w6692_bc *bhw = bch->hw; w6692_bc *bhw = bch->hw;
w6692pci *card = bch->inst.data; w6692pci *card = bch->inst.privat;
if ((card->pots == 0) || (bch->protocol != ISDN_PID_L1_B_64TRANS)) if ((card->pots == 0) || (bch->protocol != ISDN_PID_L1_B_64TRANS))
return(-ENODEV); return(-ENODEV);
@ -567,7 +567,7 @@ static int
disable_pots(bchannel_t *bch) disable_pots(bchannel_t *bch)
{ {
w6692_bc *bhw = bch->hw; w6692_bc *bhw = bch->hw;
w6692pci *card = bch->inst.data; w6692pci *card = bch->inst.privat;
if (card->pots == 0) if (card->pots == 0)
return(-ENODEV); return(-ENODEV);
@ -580,7 +580,7 @@ disable_pots(bchannel_t *bch)
static int static int
mode_w6692(bchannel_t *bch, int bc, int protocol) mode_w6692(bchannel_t *bch, int bc, int protocol)
{ {
w6692pci *card = bch->inst.data; w6692pci *card = bch->inst.privat;
w6692_bc *bhw = bch->hw; w6692_bc *bhw = bch->hw;
@ -605,7 +605,6 @@ mode_w6692(bchannel_t *bch, int bc, int protocol)
dev_kfree_skb(bch->next_skb); dev_kfree_skb(bch->next_skb);
bch->next_skb = NULL; bch->next_skb = NULL;
} }
discard_queue(&bch->rqueue);
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);
break; break;
@ -615,7 +614,6 @@ mode_w6692(bchannel_t *bch, int bc, int protocol)
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);
bch_sched_event(bch, B_XMTBUFREADY);
break; break;
case (ISDN_PID_L1_B_64HDLC): case (ISDN_PID_L1_B_64HDLC):
bch->protocol = protocol; bch->protocol = protocol;
@ -625,7 +623,6 @@ mode_w6692(bchannel_t *bch, int bc, int protocol)
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);
bch_sched_event(bch, B_XMTBUFREADY);
break; break;
default: default:
mISDN_debugprint(&bch->inst, "prot not known %x", protocol); mISDN_debugprint(&bch->inst, "prot not known %x", protocol);
@ -643,13 +640,21 @@ send_next(bchannel_t *bch)
W6692_fill_Bfifo(bch); W6692_fill_Bfifo(bch);
else { else {
bch->tx_idx = 0; bch->tx_idx = 0;
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) { if (test_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
if (bch->next_skb) { struct sk_buff *skb = bch->next_skb;
bch->tx_len = bch->next_skb->len; if (skb) {
memcpy(bch->tx_buf, bch->next_skb->data, bch->tx_len); mISDN_head_t *hh = mISDN_HEAD_P(skb);
bch->next_skb = NULL;
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
bch->tx_len = skb->len;
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; bch->tx_len = 0;
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(BC_FLG_TX_BUSY, &bch->Flag);
} }
@ -657,7 +662,6 @@ send_next(bchannel_t *bch)
bch->tx_len = 0; bch->tx_len = 0;
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag); test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
} }
bch_sched_event(bch, B_XMTBUFREADY);
} }
} }
@ -711,9 +715,8 @@ W6692B_interrupt(w6692pci *card, int ch)
printk(KERN_WARNING "Bchan receive out of memory\n"); printk(KERN_WARNING "Bchan receive out of memory\n");
else { else {
memcpy(skb_put(skb, bch->rx_idx), bch->rx_buf, bch->rx_idx); memcpy(skb_put(skb, bch->rx_idx), bch->rx_buf, bch->rx_idx);
skb_queue_tail(&bch->rqueue, skb); queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
} }
bch_sched_event(bch, B_RCVBUFREADY);
} }
} }
bch->rx_idx = 0; bch->rx_idx = 0;
@ -739,9 +742,8 @@ W6692B_interrupt(w6692pci *card, int ch)
printk(KERN_WARNING "Bchan receive out of memory\n"); printk(KERN_WARNING "Bchan receive out of memory\n");
else { else {
memcpy(skb_put(skb, bch->rx_idx), bch->rx_buf, bch->rx_idx); memcpy(skb_put(skb, bch->rx_idx), bch->rx_buf, bch->rx_idx);
skb_queue_tail(&bch->rqueue, skb); queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
} }
bch_sched_event(bch, B_RCVBUFREADY);
bch->rx_idx = 0; bch->rx_idx = 0;
} }
} }
@ -887,7 +889,7 @@ dbusy_timer_handler(dchannel_t *dch)
int rbch, star; int rbch, star;
if (test_bit(FLG_DBUSY_TIMER, &dch->DFlags)) { if (test_bit(FLG_DBUSY_TIMER, &dch->DFlags)) {
if (dch->inst.lock(dch->inst.data, 1)) { if (dch->inst.lock(dch->inst.privat, 1)) {
dch->dbusytimer.expires = jiffies + 1; dch->dbusytimer.expires = jiffies + 1;
add_timer(&dch->dbusytimer); add_timer(&dch->dbusytimer);
return; return;
@ -911,7 +913,7 @@ dbusy_timer_handler(dchannel_t *dch)
/* Transmitter reset */ /* Transmitter reset */
WriteW6692(card, W_D_CMDR, W_D_CMDR_XRST); /* Transmitter reset */ WriteW6692(card, W_D_CMDR, W_D_CMDR_XRST); /* Transmitter reset */
} }
dch->inst.unlock(dch->inst.data); dch->inst.unlock(dch->inst.privat);
} }
} }
@ -1036,16 +1038,12 @@ MODULE_PARM(layermask, MODULE_PARM_T);
/* Layer2 -> Layer 1 Transfer */ /* Layer2 -> Layer 1 Transfer */
/******************************/ /******************************/
static int static int
w6692_l2l1B(mISDNif_t *hif, struct sk_buff *skb) w6692_l2l1B(mISDNinstance_t *inst, struct sk_buff *skb)
{ {
bchannel_t *bch; bchannel_t *bch = container_of(inst, bchannel_t, inst);
int ret = -EINVAL; int ret = 0;
mISDN_head_t *hh; mISDN_head_t *hh = mISDN_HEAD_P(skb);
if (!hif || !skb)
return(ret);
hh = mISDN_HEAD_P(skb);
bch = hif->fdata;
if ((hh->prim == PH_DATA_REQ) || if ((hh->prim == PH_DATA_REQ) ||
(hh->prim == (DL_DATA | REQUEST))) { (hh->prim == (DL_DATA | REQUEST))) {
if (bch->next_skb) { if (bch->next_skb) {
@ -1053,46 +1051,50 @@ w6692_l2l1B(mISDNif_t *hif, struct sk_buff *skb)
__FUNCTION__); __FUNCTION__);
return(-EBUSY); return(-EBUSY);
} }
bch->inst.lock(bch->inst.data, 0); if (skb->len <= 0)
return(-EINVAL);
bch->inst.lock(bch->inst.privat, 0);
if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) { if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag); test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
bch->next_skb = skb; bch->next_skb = skb;
bch->inst.unlock(bch->inst.data); bch->inst.unlock(bch->inst.privat);
return(0); return(0);
} else { } else {
bch->tx_len = skb->len; bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len); memcpy(bch->tx_buf, skb->data, bch->tx_len);
bch->tx_idx = 0; bch->tx_idx = 0;
W6692_fill_Bfifo(bch); W6692_fill_Bfifo(bch);
bch->inst.unlock(bch->inst.data); bch->inst.unlock(bch->inst.privat);
#ifdef FIXME
if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV) if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
&& bch->dev) && bch->dev)
hif = &bch->dev->rport.pif; hif = &bch->dev->rport.pif;
else else
hif = &bch->inst.up; hif = &bch->inst.up;
#endif
skb_trim(skb, 0); skb_trim(skb, 0);
return(if_newhead(hif, hh->prim | CONFIRM, return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM,
hh->dinfo, skb)); hh->dinfo, skb));
} }
} else if ((hh->prim == (PH_ACTIVATE | REQUEST)) || } 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(BC_FLG_ACTIV, &bch->Flag)) {
ret = 0; bch->inst.lock(bch->inst.privat, 0);
else {
bch->inst.lock(bch->inst.data, 0);
ret = mode_w6692(bch, bch->channel, bch->inst.pid.protocol[1]); ret = mode_w6692(bch, bch->channel, bch->inst.pid.protocol[1]);
bch->inst.unlock(bch->inst.data); bch->inst.unlock(bch->inst.privat);
} }
#ifdef FIXME
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV) if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
if (bch->dev) if (bch->dev)
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
skb_trim(skb, 0); skb_trim(skb, 0);
return(if_newhead(&bch->inst.up, hh->prim | CONFIRM, ret, skb)); return(mISDN_queueup_newhead(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 == (MGR_DISCONNECT | REQUEST))) { ((hh->prim == (PH_CONTROL | REQUEST) && (hh->dinfo == HW_DEACTIVATE)))) {
bch->inst.lock(bch->inst.data, 0); bch->inst.lock(bch->inst.privat, 0);
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) { if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
dev_kfree_skb(bch->next_skb); dev_kfree_skb(bch->next_skb);
bch->next_skb = NULL; bch->next_skb = NULL;
@ -1100,20 +1102,20 @@ w6692_l2l1B(mISDNif_t *hif, struct sk_buff *skb)
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag); test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
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(BC_FLG_ACTIV, &bch->Flag);
bch->inst.unlock(bch->inst.data); bch->inst.unlock(bch->inst.privat);
skb_trim(skb, 0); skb_trim(skb, 0);
if (hh->prim != (MGR_DISCONNECT | REQUEST)) { if (hh->prim != (PH_CONTROL | REQUEST)) {
#ifdef FIXME
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV) if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
if (bch->dev) if (bch->dev)
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);
if (!if_newhead(&bch->inst.up, hh->prim | CONFIRM, 0, skb)) #endif
if (!mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, 0, skb))
return(0); return(0);
} }
ret = 0;
} else if (hh->prim == (PH_CONTROL | REQUEST)) { } else if (hh->prim == (PH_CONTROL | REQUEST)) {
ret = 0; bch->inst.lock(bch->inst.privat, 0);
bch->inst.lock(bch->inst.data, 0);
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) {
@ -1124,10 +1126,11 @@ w6692_l2l1B(mISDNif_t *hif, struct sk_buff *skb)
ret = setvolume(bch, 0, skb); ret = setvolume(bch, 0, skb);
} else } else
ret = -EINVAL; ret = -EINVAL;
bch->inst.unlock(bch->inst.data); bch->inst.unlock(bch->inst.privat);
} else { } else {
printk(KERN_WARNING "%s: unknown prim(%x)\n", printk(KERN_WARNING "%s: unknown prim(%x)\n",
__FUNCTION__, hh->prim); __FUNCTION__, hh->prim);
ret = -EINVAL;
} }
if (!ret) if (!ret)
dev_kfree_skb(skb); dev_kfree_skb(skb);
@ -1135,48 +1138,43 @@ w6692_l2l1B(mISDNif_t *hif, struct sk_buff *skb)
} }
static int static int
w6692_l1hwD(mISDNif_t *hif, struct sk_buff *skb) w6692_l1hwD(mISDNinstance_t *inst, struct sk_buff *skb)
{ {
dchannel_t *dch; dchannel_t *dch = container_of(inst, dchannel_t, inst);
int ret = -EINVAL; int ret = 0;
mISDN_head_t *hh; mISDN_head_t *hh = mISDN_HEAD_P(skb);
if (!hif || !skb)
return(ret);
hh = mISDN_HEAD_P(skb);
dch = hif->fdata;
ret = 0;
if (hh->prim == PH_DATA_REQ) { if (hh->prim == PH_DATA_REQ) {
if (dch->next_skb) { if (dch->next_skb) {
mISDN_debugprint(&dch->inst, "w6692 l2l1 next_skb exist this shouldn't happen"); mISDN_debugprint(&dch->inst, "w6692 l2l1 next_skb exist this shouldn't happen");
return(-EBUSY); return(-EBUSY);
} }
dch->inst.lock(dch->inst.data,0); dch->inst.lock(dch->inst.privat,0);
if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) { if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) {
test_and_set_bit(FLG_TX_NEXT, &dch->DFlags); test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
dch->next_skb = skb; dch->next_skb = skb;
dch->inst.unlock(dch->inst.data); dch->inst.unlock(dch->inst.privat);
return(0); return(0);
} else { } else {
dch->tx_len = skb->len; dch->tx_len = skb->len;
memcpy(dch->tx_buf, skb->data, dch->tx_len); memcpy(dch->tx_buf, skb->data, dch->tx_len);
dch->tx_idx = 0; dch->tx_idx = 0;
W6692_fill_Dfifo(dch->hw); W6692_fill_Dfifo(dch->hw);
dch->inst.unlock(dch->inst.data); dch->inst.unlock(dch->inst.privat);
return(if_newhead(&dch->inst.up, PH_DATA_CNF, return(mISDN_queueup_newhead(inst, 0, PH_DATA_CNF,
hh->dinfo, skb)); hh->dinfo, skb));
} }
} else if (hh->prim == (PH_SIGNAL | REQUEST)) { } else if (hh->prim == (PH_SIGNAL | REQUEST)) {
dch->inst.lock(dch->inst.data,0); dch->inst.lock(dch->inst.privat,0);
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;
dch->inst.unlock(dch->inst.data); dch->inst.unlock(dch->inst.privat);
} else if (hh->prim == (PH_CONTROL | REQUEST)) { } else if (hh->prim == (PH_CONTROL | REQUEST)) {
dch->inst.lock(dch->inst.data,0); dch->inst.lock(dch->inst.privat,0);
if (hh->dinfo == HW_RESET) { if (hh->dinfo == HW_RESET) {
if (dch->ph_state != W_L1IND_DRD) if (dch->ph_state != W_L1IND_DRD)
ph_command(dch->hw, W_L1CMD_RST); ph_command(dch->hw, W_L1CMD_RST);
@ -1184,7 +1182,6 @@ w6692_l1hwD(mISDNif_t *hif, struct sk_buff *skb)
} else if (hh->dinfo == HW_POWERUP) { } else if (hh->dinfo == HW_POWERUP) {
ph_command(dch->hw, W_L1CMD_ECK); ph_command(dch->hw, W_L1CMD_ECK);
} else if (hh->dinfo == HW_DEACTIVATE) { } else if (hh->dinfo == HW_DEACTIVATE) {
discard_queue(&dch->rqueue);
if (dch->next_skb) { if (dch->next_skb) {
dev_kfree_skb(dch->next_skb); dev_kfree_skb(dch->next_skb);
dch->next_skb = NULL; dch->next_skb = NULL;
@ -1193,8 +1190,10 @@ w6692_l1hwD(mISDNif_t *hif, struct sk_buff *skb)
test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags); test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags)) if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
del_timer(&dch->dbusytimer); del_timer(&dch->dbusytimer);
#ifdef FIXME
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags)) if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
dchannel_sched_event(dch, D_CLEARBUSY); dchannel_sched_event(dch, D_CLEARBUSY);
#endif
} else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) { } else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) {
u_char val = 0; u_char val = 0;
@ -1209,7 +1208,7 @@ w6692_l1hwD(mISDNif_t *hif, struct sk_buff *skb)
hh->dinfo); hh->dinfo);
ret = -EINVAL; ret = -EINVAL;
} }
dch->inst.unlock(dch->inst.data); dch->inst.unlock(dch->inst.privat);
} else { } else {
if (dch->debug & L1_DEB_WARN) if (dch->debug & L1_DEB_WARN)
mISDN_debugprint(&dch->inst, "w6692_l1hw unknown prim %x", mISDN_debugprint(&dch->inst, "w6692_l1hw unknown prim %x",
@ -1275,7 +1274,6 @@ release_card(w6692pci *card)
mISDN_free_bch(&card->bch[1]); mISDN_free_bch(&card->bch[1]);
mISDN_free_bch(&card->bch[0]); mISDN_free_bch(&card->bch[0]);
mISDN_free_dch(&card->dch); mISDN_free_dch(&card->dch);
w6692.ctrl(card->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &card->dch.inst.up);
w6692.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL); w6692.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
list_del(&card->list); list_del(&card->list);
unlock_dev(card); unlock_dev(card);
@ -1328,22 +1326,17 @@ w6692_manager(void *data, u_int prim, void *arg) {
bch_set_para(&card->bch[channel], &inst->st->para); bch_set_para(&card->bch[channel], &inst->st->para);
break; break;
case MGR_UNREGLAYER | REQUEST: case MGR_UNREGLAYER | REQUEST:
if (channel == 2) {
inst->down.fdata = &card->dch;
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 (w6692_l1hwD(&inst->down, skb)) if (channel == 2) {
if (w6692_l1hwD(inst, skb))
dev_kfree_skb(skb); dev_kfree_skb(skb);
}
} else { } else {
inst->down.fdata = &card->bch[channel]; if (w6692_l2l1B(inst, skb))
if ((skb = create_link_skb(MGR_DISCONNECT | REQUEST,
0, 0, NULL, 0))) {
if (w6692_l2l1B(&inst->down, skb))
dev_kfree_skb(skb); dev_kfree_skb(skb);
} }
} } else
w6692.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up); 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);
break; break;
case MGR_CLRSTPARA | INDICATION: case MGR_CLRSTPARA | INDICATION:
@ -1361,33 +1354,18 @@ w6692_manager(void *data, u_int prim, void *arg) {
w6692.refcnt--; w6692.refcnt--;
} }
break; break;
case MGR_CONNECT | REQUEST:
return(mISDN_ConnectIF(inst, arg));
case MGR_SETIF | REQUEST:
case MGR_SETIF | INDICATION:
if (channel==2)
return(mISDN_SetIF(inst, arg, prim, w6692_l1hwD, NULL,
&card->dch));
else
return(mISDN_SetIF(inst, arg, prim, w6692_l2l1B, NULL,
&card->bch[channel]));
break;
case MGR_DISCONNECT | REQUEST:
case MGR_DISCONNECT | INDICATION:
return(mISDN_DisConnectIF(inst, arg));
case MGR_SETSTACK | INDICATION: case MGR_SETSTACK | INDICATION:
if ((channel!=2) && (inst->pid.global == 2)) { if ((channel!=2) && (inst->pid.global == 2)) {
inst->down.fdata = &card->bch[channel];
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->down, skb)) if (w6692_l2l1B(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)
if_link(&inst->up, DL_ESTABLISH | INDICATION, mISDN_queue_data(inst, FLG_MSG_UP, DL_ESTABLISH | INDICATION,
0, 0, NULL, 0); 0, 0, NULL, 0);
else else
if_link(&inst->up, PH_ACTIVATE | INDICATION, mISDN_queue_data(inst, FLG_MSG_UP, PH_ACTIVATE | INDICATION,
0, 0, NULL, 0); 0, 0, NULL, 0);
} }
break; break;
@ -1425,14 +1403,14 @@ static int __devinit setup_instance(w6692pci *card)
card->dch.inst.unlock = unlock_dev; card->dch.inst.unlock = unlock_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); mISDN_init_instance(&card->dch.inst, &w6692, card, w6692_l1hwD);
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_init_dch(&card->dch); mISDN_init_dch(&card->dch);
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); mISDN_init_instance(&card->bch[i].inst, &w6692, card, w6692_l2l1B);
card->bch[i].inst.pid.layermask = ISDN_LAYER(0); card->bch[i].inst.pid.layermask = ISDN_LAYER(0);
card->bch[i].inst.lock = lock_dev; card->bch[i].inst.lock = lock_dev;
card->bch[i].inst.unlock = unlock_dev; card->bch[i].inst.unlock = unlock_dev;