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

View File

@ -5,7 +5,8 @@
* This file is (c) under GNU PUBLIC LICENSE
*
*/
#ifndef _mISDN_BCHANNEL_H
#define _mISDN_BCHANNEL_H
#include <linux/mISDNif.h>
#ifdef HAS_WORKQUEUE
#include <linux/workqueue.h>
@ -22,6 +23,7 @@
#ifdef MISDN_MEMDEBUG
#include "memdbg.h"
#endif
#include "helper.h"
#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
static inline void
bch_sched_event(bchannel_t *bch, int event)
@ -100,3 +115,4 @@ bch_sched_event(bchannel_t *bch, int event)
schedule_work(&bch->work);
}
#endif
#endif

View File

@ -101,7 +101,6 @@
#include "bchannel.h"
#include "layer1.h"
#include "dsp.h"
#include "helper.h"
#include "debug.h"
#include <linux/isdn_compat.h>
@ -1013,11 +1012,12 @@ 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;
mISDN_head_t *hh;
if (skb) {
dch->next_skb = NULL;
test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
hh = mISDN_HEAD_P(skb);
dch->tx_idx = 0;
dch->tx_len = skb->len;
@ -1025,8 +1025,10 @@ next_frame:
skb_trim(skb, 0);
if (mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_CNF, hh->dinfo, skb)) dev_kfree_skb(skb);
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);
}
}
test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
@ -1034,28 +1036,23 @@ next_frame:
}
if (bch) {
// 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;
mISDN_head_t *hh;
u_int pr;
if (skb) {
bch->next_skb = NULL;
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
hh = mISDN_HEAD_P(skb);
bch->tx_idx = 0;
bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len);
skb_trim(skb, 0);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
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);
}
queue_bch_frame(bch, CONFIRM, hh->dinfo, skb);
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");
}
}
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
@ -1262,17 +1259,8 @@ next_frame:
// schedule D-channel event
mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_IND, MISDN_ID_ANY, skb);
}
if (bch) {
// schedule B-channel event
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);
}
}
if (bch)
queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
*idx = 0;
goto next_frame;
}
@ -1301,19 +1289,8 @@ next_frame:
//dchannel_sched_event(dch, D_RCVBUFREADY);
mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_IND, MISDN_ID_ANY, skb);
}
if (bch) {
// schedule B-channel event
//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);
}
}
if (bch)
queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
}
}

View File

@ -34,7 +34,6 @@
#include "bchannel.h"
#include "hfc_pci.h"
#include "layer1.h"
#include "helper.h"
#include "debug.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;
int new_z2, fcnt, maxlen;
u_int pr;
struct sk_buff *skb;
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 */
memcpy(ptr, ptr1, fcnt); /* rest */
}
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);
}
queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
}
*z2r = new_z2; /* new position */
@ -606,7 +597,6 @@ main_rec_hfcpci(bchannel_t *bch)
hfc_pci_t *hc = bch->hw;
int rcnt, real_fifo;
int receive, count = 5;
u_int pr;
struct sk_buff *skb;
bzfifo_type *bz;
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)",
bch->channel, zp->z1, zp->z2, rcnt);
if ((skb = hfcpci_empty_fifo(bch, bz, bdata, rcnt))) {
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);
}
queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
}
rcnt = bz->f1 - bz->f2;
if (rcnt < 0)
@ -814,28 +797,23 @@ next_t_frame:
} else if (bch->debug & L1_DEB_HSCX)
mISDN_debugprint(&bch->inst, "hfcpci_fill_fifo_trans ch(%x) frame length %d discarded",
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;
mISDN_head_t *hh;
u_int pr;
if (skb) {
bch->next_skb = NULL;
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
hh = mISDN_HEAD_P(skb);
bch->tx_idx = 0;
bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len);
skb_trim(skb, 0);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
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);
}
queue_bch_frame(bch, CONFIRM, hh->dinfo, skb);
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");
}
}
bch->tx_len = 0;
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
@ -1288,28 +1266,22 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
hfcpci_fill_fifo(bch);
} else {
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;
mISDN_head_t *hh;
u_int pr;
if (skb) {
bch->next_skb = NULL;
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
hh = mISDN_HEAD_P(skb);
bch->tx_idx = 0;
bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len);
skb_trim(skb, 0);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
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);
}
queue_bch_frame(bch, CONFIRM, hh->dinfo, skb);
hfcpci_fill_fifo(bch);
} else {
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);
bch->tx_len = 0;
}
@ -1330,28 +1302,22 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
hfcpci_fill_fifo(bch);
} else {
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;
mISDN_head_t *hh;
u_int pr;
if (skb) {
bch->next_skb = NULL;
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
hh = mISDN_HEAD_P(skb);
bch->tx_idx = 0;
bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len);
skb_trim(skb, 0);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
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);
}
queue_bch_frame(bch, CONFIRM, hh->dinfo, skb);
hfcpci_fill_fifo(bch);
} else {
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);
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) {
hfcpci_fill_dfifo(hc);
} else {
if (test_and_clear_bit(FLG_TX_NEXT, &hc->dch.DFlags)) {
if (hc->dch.next_skb) {
mISDN_head_t *hh;
hc->dch.tx_len = hc->dch.next_skb->len;
memcpy(hc->dch.tx_buf,
hc->dch.next_skb->data,
hc->dch.tx_len);
if (test_bit(FLG_TX_NEXT, &hc->dch.DFlags)) {
struct sk_buff *skb = hc->dch.next_skb;
if (skb) {
mISDN_head_t *hh = mISDN_HEAD_P(skb);
hc->dch.next_skb= NULL;
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;
hfcpci_fill_dfifo(hc);
skb_trim(hc->dch.next_skb, 0);
hh = mISDN_HEAD_P(hc->dch.next_skb);
if (mISDN_queueup_newhead(&hc->dch.inst, 0, PH_DATA_CNF, hh->dinfo, hc->dch.next_skb))
dev_kfree_skb(hc->dch.next_skb);
hc->dch.next_skb= NULL;
skb_trim(skb, 0);
if (mISDN_queueup_newhead(&hc->dch.inst, 0, PH_DATA_CNF, hh->dinfo, skb))
dev_kfree_skb(skb);
} else {
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);
}
} else
@ -1432,13 +1399,12 @@ HFCD_l1hw(mISDNinstance_t *inst, struct sk_buff *skb)
{
dchannel_t *dch;
hfc_pci_t *hc;
int ret = -EINVAL;
int ret = 0;
mISDN_head_t *hh;
hh = mISDN_HEAD_P(skb);
dch = container_of(inst, dchannel_t, inst);
hc = inst->privat;
ret = 0;
if (hh->prim == PH_DATA_REQ) {
if (dch->next_skb) {
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);
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
del_timer(&dch->dbusytimer);
#if 0
#ifdef FIXME
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
dchannel_sched_event(&hc->dch, D_CLEARBUSY);
#endif
@ -1884,12 +1850,13 @@ hfcpci_l2l1(mISDNinstance_t *inst, struct sk_buff *skb)
hh = mISDN_HEAD_P(skb);
if ((hh->prim == PH_DATA_REQ) ||
(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) {
printk(KERN_WARNING "%s: next_skb exist ERROR\n",
__FUNCTION__);
return(-EBUSY);
}
if (skb->len <= 0)
return(-EINVAL);
bch->inst.lock(hc, 0);
if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);

View File

@ -35,7 +35,6 @@
#include "dchannel.h"
#include "bchannel.h"
#include "layer1.h"
#include "helper.h"
#include "debug.h"
#include "hw_lock.h"
#include "hfcs_usb.h"
@ -221,8 +220,8 @@ static struct usb_device_id hfcsusb_idtab[] = {
};
/* some function prototypes */
static int hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb);
static int hfcsusb_l2l1B(mISDNif_t * hif, struct sk_buff *skb);
static int hfcsusb_l1hwD(mISDNinstance_t *inst, 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 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);
break;
case MGR_UNREGLAYER | REQUEST:
if (channel == 2) {
inst->down.fdata = &card->dch;
if ((skb =
create_link_skb(PH_CONTROL | REQUEST,
HW_DEACTIVATE, 0,
NULL, 0))) {
if (hfcsusb_l1hwD
(&inst->down, skb))
if ((skb = create_link_skb(PH_CONTROL | REQUEST,
HW_DEACTIVATE, 0, NULL, 0))) {
if (channel == 2) {
if (hfcsusb_l1hwD(inst, skb))
dev_kfree_skb(skb);
} else {
if (hfcsusb_l2l1B(inst, skb))
dev_kfree_skb(skb);
}
} else {
inst->down.fdata = &card->bch[channel];
if ((skb =
create_link_skb(MGR_DISCONNECT |
REQUEST, 0, 0, NULL,
0))) {
if (hfcsusb_l2l1B
(&inst->down, skb))
dev_kfree_skb(skb);
}
}
hw_mISDNObj.ctrl(inst->up.peer,
MGR_DISCONNECT | REQUEST,
&inst->up);
hw_mISDNObj.ctrl(inst, MGR_UNREGLAYER | REQUEST,
NULL);
} else
printk(KERN_WARNING "no SKB in %s MGR_UNREGLAYER | REQUEST\n", __FUNCTION__);
hw_mISDNObj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
break;
case MGR_CLRSTPARA | INDICATION:
arg = NULL;
@ -481,40 +466,18 @@ hfcsusb_manager(void *data, u_int prim, void *arg)
}
*/
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:
if ((channel != 2) && (inst->pid.global == 2)) {
inst->down.fdata = &card->bch[channel];
if ((skb =
create_link_skb(PH_ACTIVATE | REQUEST,
0, 0, NULL, 0))) {
if (hfcsusb_l2l1B
(&inst->down, skb))
if ((skb = create_link_skb(PH_ACTIVATE | REQUEST,
0, 0, NULL, 0))) {
if (hfcsusb_l2l1B(inst, skb))
dev_kfree_skb(skb);
}
if (inst->pid.protocol[2] ==
ISDN_PID_L2_B_TRANS)
if_link(&inst->up,
DL_ESTABLISH | INDICATION,
if (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS)
mISDN_queue_data(inst, FLG_MSG_UP, DL_ESTABLISH | INDICATION,
0, 0, NULL, 0);
else
if_link(&inst->up,
PH_ACTIVATE | INDICATION,
mISDN_queue_data(inst, FLG_MSG_UP, PH_ACTIVATE | INDICATION,
0, 0, NULL, 0);
}
break;
@ -547,11 +510,7 @@ S0_new_state(dchannel_t * dch)
{
u_int prim = PH_SIGNAL | INDICATION;
u_int para = 0;
mISDNif_t *upif = &dch->inst.up;
hfcsusb_t *card = dch->hw;
if (!test_and_clear_bit(D_L1STATECHANGE, &dch->event))
return;
hfcsusb_t *card = dch->inst.privat;
if (card->hw_mode & HW_MODE_TE) {
if (dch->debug)
@ -589,7 +548,7 @@ S0_new_state(dchannel_t * dch)
"%s: NT %d",
__FUNCTION__, dch->ph_state);
dch->inst.lock(dch->inst.data, 0);
dch->inst.lock(dch->inst.privat, 0);
switch (dch->ph_state) {
case (1):
card->nt_timer = 0;
@ -610,8 +569,8 @@ S0_new_state(dchannel_t * dch)
/* allow G2 -> G3 transition */
queued_Write_hfc(card, HFCUSB_STATES, 2 | HFCUSB_NT_G2_G3);
}
upif = NULL;
break;
dch->inst.unlock(dch->inst.privat);
return;
case (3):
card->nt_timer = 0;
card->hw_mode &= ~NT_ACTIVATION_TIMER;
@ -622,18 +581,14 @@ S0_new_state(dchannel_t * dch)
case (4):
card->nt_timer = 0;
card->hw_mode &= ~NT_ACTIVATION_TIMER;
upif = NULL;
break;
dch->inst.unlock(dch->inst.privat);
return;
default:
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;
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 */
hfcsusb_t *card = bch->inst.data;
hfcsusb_t *card = bch->inst.privat;
if (bch->debug & L1_DEB_HSCX)
mISDN_debugprint(&bch->inst,
@ -744,10 +699,6 @@ mode_bchannel(bchannel_t * bch, int bc, int protocol)
if (protocol > ISDN_PID_NONE) {
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 {
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 */
/*************************************/
static int
hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb)
hfcsusb_l1hwD(mISDNinstance_t *inst, struct sk_buff *skb)
{
dchannel_t *dch;;
int ret = -EINVAL;
mISDN_head_t *hh;
hfcsusb_t *card;
dchannel_t *dch;
int ret = 0;
mISDN_head_t *hh;
hfcsusb_t *card;
if (!hif || !skb)
return (ret);
hh = mISDN_HEAD_P(skb);
dch = hif->fdata;
card = dch->hw;
ret = 0;
dch = container_of(inst, dchannel_t, inst);
card = inst->privat;
if (hh->prim == PH_DATA_REQ) {
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");
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)) {
test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
dch->next_skb = skb;
dch->inst.unlock(dch->inst.data);
dch->inst.unlock(dch->inst.privat);
return (0);
} else {
/* prepare buffer, which is transmitted by
@ -846,22 +794,23 @@ hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb)
dch->tx_len = skb->len;
memcpy(dch->tx_buf, skb->data, dch->tx_len);
dch->tx_idx = 0;
dch->inst.unlock(dch->inst.data);
dch->inst.unlock(dch->inst.privat);
skb_trim(skb, 0);
return (if_newhead(&dch->inst.up, PH_DATA_CNF,
hh->dinfo, skb));
return(mISDN_queueup_newhead(inst, 0, PH_DATA_CNF,
hh->dinfo, skb));
}
} 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)
hfcsusb_ph_command(dch->hw, S0_L1CMD_AR8);
else if (hh->dinfo == INFO3_P10)
hfcsusb_ph_command(dch->hw, S0_L1CMD_AR10);
else
ret = -EINVAL;
dch->inst.unlock(dch->inst.data);
dch->inst.unlock(dch->inst.privat);
} 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 (dch->ph_state != 0)
hfcsusb_ph_command(dch->hw,
@ -870,15 +819,16 @@ hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb)
} else if (hh->dinfo == HW_POWERUP) {
hfcsusb_ph_command(dch->hw, S0_L1CMD_ECK);
} else if (hh->dinfo == HW_DEACTIVATE) {
discard_queue(&dch->rqueue);
if (dch->next_skb) {
dev_kfree_skb(dch->next_skb);
dch->next_skb = NULL;
}
test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
#ifdef FIXME
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
dchannel_sched_event(dch, D_CLEARBUSY);
#endif
} else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) {
u_char val = 0;
@ -894,9 +844,9 @@ hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb)
hh->dinfo);
ret = -EINVAL;
}
dch->inst.unlock(dch->inst.data);
dch->inst.unlock(dch->inst.privat);
} 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) {
hfcsusb_ph_command(dch->hw, HFC_L1_ACTIVATE_NT);
} else {
@ -905,9 +855,9 @@ hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb)
__FUNCTION__);
ret = -EINVAL;
}
dch->inst.unlock(dch->inst.data);
dch->inst.unlock(dch->inst.privat);
} 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) {
hfcsusb_ph_command(dch->hw, HFC_L1_DEACTIVATE_NT);
} else {
@ -916,7 +866,7 @@ hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb)
__FUNCTION__);
ret = -EINVAL;
}
dch->inst.unlock(dch->inst.data);
dch->inst.unlock(dch->inst.privat);
} else {
if (dch->debug & L1_DEB_WARN)
mISDN_debugprint(&dch->inst,
@ -933,32 +883,25 @@ hfcsusb_l1hwD(mISDNif_t * hif, struct sk_buff *skb)
/* Layer2 -> Layer 1 Transfer */
/******************************/
static int
hfcsusb_l2l1B(mISDNif_t * hif, struct sk_buff *skb)
hfcsusb_l2l1B(mISDNinstance_t *inst, struct sk_buff *skb)
{
bchannel_t *bch;
int ret = -EINVAL;
mISDN_head_t *hh;
hfcsusb_t *card;
bchannel_t *bch = container_of(inst, bchannel_t, inst);
int ret = 0;
mISDN_head_t *hh = mISDN_HEAD_P(skb);
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 (bch->next_skb) {
printk(KERN_WARNING "%s: next_skb exist ERROR\n",
__FUNCTION__);
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)) {
test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
bch->next_skb = skb;
bch->inst.unlock(bch->inst.data);
bch->inst.unlock(bch->inst.privat);
return (0);
} else {
/* prepare buffer, wich is transmitted by
@ -966,40 +909,39 @@ hfcsusb_l2l1B(mISDNif_t * hif, struct sk_buff *skb)
bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len);
bch->tx_idx = 0;
bch->inst.unlock(bch->inst.data);
if ((bch->inst.pid.protocol[2] ==
ISDN_PID_L2_B_RAWDEV)
&& bch->dev)
bch->inst.unlock(bch->inst.privat);
#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 (if_newhead(hif, hh->prim | CONFIRM,
hh->dinfo, skb));
return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM,
hh->dinfo, skb));
}
} else if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
(hh->prim == (DL_ESTABLISH | REQUEST))) {
if (test_and_set_bit(BC_FLG_ACTIV, &bch->Flag))
ret = 0;
else {
bch->inst.lock(bch->inst.data, 0);
ret =
mode_bchannel(bch, bch->channel,
bch->inst.pid.protocol[1]);
bch->inst.unlock(bch->inst.data);
if (!test_and_set_bit(BC_FLG_ACTIV, &bch->Flag)) {
bch->inst.lock(bch->inst.privat, 0);
ret = mode_bchannel(bch, bch->channel,
bch->inst.pid.protocol[1]);
bch->inst.unlock(bch->inst.privat);
}
#ifdef FIXME
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
if (bch->dev)
if_link(&bch->dev->rport.pif,
hh->prim | CONFIRM, 0, 0, NULL, 0);
#endif
skb_trim(skb, 0);
return (if_newhead
(&bch->inst.up, hh->prim | CONFIRM, ret, skb));
} else if ((hh->prim == (PH_DEACTIVATE | REQUEST))
|| (hh->prim == (DL_RELEASE | REQUEST))
|| (hh->prim == (MGR_DISCONNECT | REQUEST))) {
return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, ret, skb));
} else if ((hh->prim == (PH_DEACTIVATE | REQUEST)) ||
(hh->prim == (DL_RELEASE | 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)) {
dev_kfree_skb(bch->next_skb);
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);
mode_bchannel(bch, bch->channel, ISDN_PID_NONE);
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);
if (hh->prim != (MGR_DISCONNECT | REQUEST)) {
if (bch->inst.pid.protocol[2] ==
ISDN_PID_L2_B_RAWDEV)
if (hh->prim != (PH_CONTROL | REQUEST)) {
#ifdef FIXME
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
if (bch->dev)
if_link(&bch->dev->rport.pif,
hh->prim | CONFIRM, 0, 0,
NULL, 0);
if (!if_newhead
(&bch->inst.up, hh->prim | CONFIRM, 0, skb))
return (0);
hh->prim | CONFIRM, 0, 0, NULL, 0);
#endif
if (!mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, 0, skb))
return(0);
}
ret = 0;
} else if (hh->prim == (PH_CONTROL | REQUEST)) {
// do not handle PH_CONTROL | REQUEST ??
ret = -EINVAL;
} else {
printk(KERN_WARNING "%s: unknown prim(%x)\n",
__FUNCTION__, hh->prim);
__FUNCTION__, hh->prim);
ret = -EINVAL;
}
if (!ret)
dev_kfree_skb(skb);
@ -1039,11 +980,11 @@ hfcsusb_l2l1B(mISDNif_t * hif, struct sk_buff *skb)
static void
collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish)
{
hfcsusb_t *card = fifo->card;
struct sk_buff *skb;
u_char *ptr;
int fifon;
int i;
hfcsusb_t *card = fifo->card;
struct sk_buff *skb;
u_char *ptr;
int fifon;
int i;
fifon = fifo->fifonum;
@ -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 (fifo->skbuff->len >= 128) {
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");
else {
ptr =
skb_put(skb,
fifo->skbuff->
len);
memcpy(ptr, fifo->skbuff->data,
fifo->skbuff->len);
ptr = skb_put(skb, fifo->skbuff->len);
memcpy(ptr, fifo->skbuff->data, fifo->skbuff->len);
dev_kfree_skb(fifo->skbuff);
fifo->skbuff=NULL;
skb_queue_tail(&card->bch[fifo->bch_idx].
rqueue,
skb);
bch_sched_event(&card->bch[fifo->bch_idx], B_RCVBUFREADY);
queue_bch_frame(&card->bch[fifo->bch_idx],
INDICATION, MISDN_ID_ANY, skb);
}
}
return;
@ -1115,28 +1048,15 @@ collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish)
switch (fifon) {
case HFCUSB_D_RX:
if ((skb =
alloc_stack_skb(fifo->skbuff->
len,
card->dch.
up_headerlen)))
{
ptr =
skb_put(skb,
fifo->skbuff->
len);
memcpy(ptr, fifo->skbuff->data, fifo->skbuff->len);
if ((skb = alloc_stack_skb(fifo->skbuff->len,
card->dch.up_headerlen))) {
ptr = skb_put(skb, fifo->skbuff->len);
memcpy(ptr, fifo->skbuff->data,
fifo->skbuff->len);
dev_kfree_skb(fifo->skbuff);
fifo->skbuff=NULL;
skb_queue_tail(&card->dch.
rqueue,
skb);
dchannel_sched_event
(&card->dch,
D_RCVBUFREADY);
mISDN_queueup_newhead(&card->dch.inst, 0,
PH_DATA_IND, MISDN_ID_ANY, skb);
} else {
printk(KERN_WARNING
"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_B2_RX:
if (card->bch[fifo->bch_idx].protocol > ISDN_PID_NONE) {
if ((skb =
alloc_stack_skb(fifo->skbuff->
len,
card->
bch[fifo->bch_idx].
up_headerlen)))
if ((skb = alloc_stack_skb(fifo->skbuff->len,
card->bch[fifo->bch_idx].up_headerlen)))
{
ptr =
skb_put(skb,
fifo->skbuff->
len);
ptr = skb_put(skb, fifo->skbuff->len);
memcpy(ptr, fifo->skbuff->data, fifo->skbuff->len);
dev_kfree_skb(fifo->skbuff);
fifo->skbuff=NULL;
skb_queue_tail(&card->
bch
[fifo->bch_idx].
rqueue,
skb);
bch_sched_event(&card->
bch
[fifo->bch_idx],
B_RCVBUFREADY);
queue_bch_frame(&card->bch[fifo->bch_idx],
INDICATION, MISDN_ID_ANY, skb);
} else {
printk(KERN_WARNING
"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
next_d_tx_frame(hfcsusb_t * card)
{
if (test_and_clear_bit(FLG_TX_NEXT, &card->dch.DFlags)) {
if (card->dch.next_skb) {
card->dch.tx_len = card->dch.next_skb->len;
memcpy(card->dch.tx_buf,
card->dch.next_skb->data, card->dch.tx_len);
if (test_bit(FLG_TX_NEXT, &card->dch.DFlags)) {
struct sk_buff *skb = card->dch.next_skb;
if (skb) {
mISDN_head_t *hh = mISDN_HEAD_P(skb);
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;
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 {
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);
}
} else
@ -1391,20 +1302,23 @@ next_d_tx_frame(hfcsusb_t * card)
void
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 (card->bch[bch_idx].next_skb) {
if (test_bit(BC_FLG_TX_NEXT, &card->bch[bch_idx].Flag)) {
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_len =
card->bch[bch_idx].next_skb->len;
memcpy(card->bch[bch_idx].tx_buf,
card->bch[bch_idx].next_skb->data,
card->bch[bch_idx].tx_len);
bch_sched_event(&card->bch[bch_idx],
B_XMTBUFREADY);
} else
card->bch[bch_idx].tx_len = skb->len;
memcpy(card->bch[bch_idx].tx_buf, skb->data, card->bch[bch_idx].tx_len);
queue_bch_frame(&card->bch[bch_idx], CONFIRM, hh->dinfo, skb);
} else {
printk(KERN_WARNING
"hfc B%i tx irq TX_NEXT without skb\n",
bch_idx);
"hfc B%i tx irq TX_NEXT without skb\n", 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)
&& (card->hw_mode & NT_ACTIVATION_TIMER)) {
if ((--card->nt_timer) < 0)
dchannel_sched_event(&card->dch, D_L1STATECHANGE);
S0_new_state(&card->dch);
}
} else {
@ -1882,8 +1796,6 @@ release_card(hfcsusb_t * card)
mISDN_free_bch(&card->bch[1]);
mISDN_free_bch(&card->bch[0]);
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);
list_del(&card->list);
unlock_dev(card);
@ -1934,7 +1846,7 @@ setup_instance(hfcsusb_t * card)
card->dch.inst.unlock = unlock_dev;
card->dch.inst.pid.layermask = ISDN_LAYER(0);
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);
mISDN_set_dchannel_pid(&pid, protocol[hfcsusb_cnt],
layermask[hfcsusb_cnt]);
@ -1944,8 +1856,7 @@ setup_instance(hfcsusb_t * card)
for (i = 0; i < 2; i++) {
card->bch[i].channel = i;
mISDN_init_instance(&card->bch[i].inst, &hw_mISDNObj,
card);
mISDN_init_instance(&card->bch[i].inst, &hw_mISDNObj, card, hfcsusb_l2l1B);
card->bch[i].inst.pid.layermask = ISDN_LAYER(0);
card->bch[i].inst.lock = lock_dev;
card->bch[i].inst.unlock = unlock_dev;
@ -1954,10 +1865,12 @@ setup_instance(hfcsusb_t * card)
card->dch.inst.name, i + 1);
mISDN_init_bch(&card->bch[i]);
card->bch[i].hw = card;
#ifdef FIXME
if (card->bch[i].dev) {
card->bch[i].dev->wport.pif.func = hfcsusb_l2l1B;
card->bch[i].dev->wport.pif.fdata = &card->bch[i];
}
#endif
}
if (protocol[hfcsusb_cnt] & 0x10) {

View File

@ -243,16 +243,16 @@ isac_xpr_irq(dchannel_t *dch)
if (dch->tx_idx < dch->tx_len) {
isac_fill_fifo(dch);
} else {
if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
struct sk_buff *skb;
mISDN_head_t *hh;
if ((skb = dch->next_skb)) {
if (test_bit(FLG_TX_NEXT, &dch->DFlags)) {
struct sk_buff *skb = dch->next_skb;
mISDN_head_t *hh = mISDN_HEAD_P(skb);
if (skb) {
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;
isac_fill_fifo(dch);
hh = mISDN_HEAD_P(skb);
skb_trim(skb, 0);
if (unlikely(mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_CNF, hh->dinfo, skb))) {
int_error();
@ -260,6 +260,7 @@ isac_xpr_irq(dchannel_t *dch)
}
} else {
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);
}
} else
@ -283,11 +284,12 @@ isac_retransmit(dchannel_t *dch)
} else {
printk(KERN_WARNING "mISDN: ISAC XDU no TX_BUSY\n");
mISDN_debugprint(&dch->inst, "ISAC XDU no TX_BUSY");
if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
struct sk_buff *skb;
mISDN_head_t *hh;
if ((skb = dch->next_skb)) {
if (test_bit(FLG_TX_NEXT, &dch->DFlags)) {
struct sk_buff *skb = dch->next_skb;
mISDN_head_t *hh = mISDN_HEAD_P(skb);
if (skb) {
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;
@ -300,6 +302,7 @@ isac_retransmit(dchannel_t *dch)
}
} else {
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 "layer1.h"
#include "helper.h"
#include "bchannel.h"
#include "isar.h"
#include "debug.h"
@ -462,7 +461,6 @@ isar_rcv_frame(bchannel_t *bch)
{
u_char *ptr;
struct sk_buff *skb;
u_int pr;
isar_hw_t *ih = bch->hw;
if (!ih->reg->clsb) {
@ -483,14 +481,7 @@ isar_rcv_frame(bchannel_t *bch)
case ISDN_PID_L1_B_MODEM_ASYNC:
if ((skb = alloc_stack_skb(ih->reg->clsb, bch->up_headerlen))) {
rcv_mbox(bch, ih->reg, (u_char *)skb_put(skb, ih->reg->clsb));
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);
}
queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
} else {
printk(KERN_WARNING "mISDN: skb out of memory\n");
bch->Write_Reg(bch->inst.privat, 1, ISAR_IIA, 0);
@ -530,14 +521,7 @@ isar_rcv_frame(bchannel_t *bch)
} else {
memcpy(skb_put(skb, bch->rx_idx-2),
bch->rx_buf, bch->rx_idx-2);
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);
}
queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
}
bch->rx_idx = 0;
}
@ -569,14 +553,7 @@ isar_rcv_frame(bchannel_t *bch)
ih->state = STFAX_ESCAPE;
// set_skb_flag(skb, DF_NOMOREDATA);
}
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);
}
queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
if (ih->reg->cmsb & SART_NMD)
deliver_status(bch, HW_MOD_NOCARR);
} else {
@ -623,14 +600,7 @@ isar_rcv_frame(bchannel_t *bch)
// if (ih->reg->cmsb & SART_NMD)
/* ABORT */
// set_skb_flag(skb, DF_NOMOREDATA);
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);
}
queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
}
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;
mISDN_head_t *hh;
u_int pr;
if (skb) {
bch->next_skb = NULL;
test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
hh = mISDN_HEAD_P(skb);
bch->tx_idx = 0;
bch->tx_len = skb->len;
memcpy(bch->tx_buf, skb->data, bch->tx_len);
isar_fill_fifo(bch);
skb_trim(skb, 0);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
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);
}
queue_bch_frame(bch, CONFIRM, hh->dinfo, skb);
} else {
bch->tx_len = 0;
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);
}
} else {
@ -1597,18 +1561,19 @@ int
isar_down(mISDNinstance_t *inst, struct sk_buff *skb)
{
bchannel_t *bch;
int ret = -EINVAL;
int ret = 0;
mISDN_head_t *hh;
hh = mISDN_HEAD_P(skb);
bch = container_of(inst, bchannel_t, inst);
ret = 0;
if ((hh->prim == PH_DATA_REQ) ||
(hh->prim == (DL_DATA | REQUEST))) {
if (bch->next_skb) {
mISDN_debugprint(&bch->inst, " l2l1 next_skb exist this shouldn't happen");
return(-EBUSY);
}
if (skb->len <= 0)
return(-EINVAL);
bch->inst.lock(bch->inst.privat, 0);
if (test_and_set_bit(BC_FLG_TX_BUSY, &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)) ||
(hh->prim == (DL_ESTABLISH | REQUEST))) {
if (test_and_set_bit(BC_FLG_ACTIV, &bch->Flag))
ret = 0;
else {
if (!test_and_set_bit(BC_FLG_ACTIV, &bch->Flag)) {
u_int bp = bch->inst.pid.protocol[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);
skb_trim(skb, 0);
if (hh->prim != (PH_CONTROL | REQUEST))
if (!mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, 0, skb))
return(0);
ret = mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, 0, skb);
} else if (hh->prim == (PH_CONTROL | REQUEST)) {
int *val;
int len;
@ -1704,6 +1666,7 @@ isar_down(mISDNinstance_t *inst, struct sk_buff *skb)
int_errtxt("wrong modulation");
/* wrong modulation or not activ */
// TODO
ret = -EINVAL;
}
} else if (hh->dinfo == HW_MOD_LASTDATA) {
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 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) {
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);
dch->inst.unlock(dch->inst.data);
prim = PH_CONTROL | INDICATION;
para = HW_RESET;
while(upif) {
if_link(upif, prim, para, 0, NULL, 0);
upif = upif->clone;
}
upif = &dch->inst.up;
dch->inst.unlock(dch->inst.privat);
mISDN_queue_data(&dch->inst, FLG_MSG_UP, PH_CONTROL | INDICATION, HW_RESET, 0, NULL, 0);
/* fall trough */
case W_L1IND_CD:
prim = PH_CONTROL | CONFIRM;
@ -195,10 +184,7 @@ W6692_new_ph(dchannel_t *dch)
default:
return;
}
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);
}
static void
@ -281,8 +267,10 @@ d_retransmit(w6692pci *card)
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
del_timer(&dch->dbusytimer);
#ifdef FIXME
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
dchannel_sched_event(dch, D_CLEARBUSY);
#endif
if (test_bit(FLG_TX_BUSY, &dch->DFlags)) {
/* Restart frame */
dch->tx_idx = 0;
@ -290,17 +278,22 @@ d_retransmit(w6692pci *card)
} else {
printk(KERN_WARNING "mISDN: w6692 XDU no TX_BUSY\n");
mISDN_debugprint(&dch->inst, "XDU no TX_BUSY");
if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
if (dch->next_skb) {
dch->tx_len = dch->next_skb->len;
memcpy(dch->tx_buf,
dch->next_skb->data,
dch->tx_len);
if (test_bit(FLG_TX_NEXT, &dch->DFlags)) {
struct sk_buff *skb = dch->next_skb;
if (skb) {
mISDN_head_t *hh = mISDN_HEAD_P(skb);
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;
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 {
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)
count = W_D_FIFO_THRESH;
W6692_empty_Dfifo(card, count);
if (card->dch.rx_skb) {
skb_queue_tail(&card->dch.rqueue, card->dch.rx_skb);
}
if (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;
dchannel_sched_event(&card->dch, D_RCVBUFREADY);
}
static void
@ -356,21 +348,29 @@ handle_txD(w6692pci *card) {
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
del_timer(&dch->dbusytimer);
#ifdef FIXME
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
dchannel_sched_event(dch, D_CLEARBUSY);
#endif
if (dch->tx_idx < dch->tx_len) {
W6692_fill_Dfifo(card);
} else {
if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
if (dch->next_skb) {
dch->tx_len = dch->next_skb->len;
memcpy(dch->tx_buf,
dch->next_skb->data, dch->tx_len);
if (test_bit(FLG_TX_NEXT, &dch->DFlags)) {
struct sk_buff *skb = dch->next_skb;
if (skb) {
mISDN_head_t *hh = mISDN_HEAD_P(skb);
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;
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 {
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);
}
} else
@ -431,7 +431,7 @@ handle_statusD(w6692pci *card) {
break;
}
}
dchannel_sched_event(dch, D_L1STATECHANGE);
W6692_new_ph(dch);
}
if (cir & W_CIR_SCC) {
v1 = ReadW6692(card, W_SQR);
@ -453,7 +453,7 @@ static void
W6692_empty_Bfifo(bchannel_t *bch, int count)
{
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))
mISDN_debugprint(&bch->inst, "empty_Bfifo %d", count);
@ -488,7 +488,7 @@ W6692_empty_Bfifo(bchannel_t *bch, int count)
static void
W6692_fill_Bfifo(bchannel_t *bch)
{
w6692pci *card = bch->inst.data;
w6692pci *card = bch->inst.privat;
int count;
u_char *ptr, cmd = W_B_CMDR_RACT | W_B_CMDR_XMS;
@ -523,7 +523,7 @@ W6692_fill_Bfifo(bchannel_t *bch)
static int
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;
u_char val;
@ -550,7 +550,7 @@ static int
enable_pots(bchannel_t *bch)
{
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))
return(-ENODEV);
@ -567,7 +567,7 @@ static int
disable_pots(bchannel_t *bch)
{
w6692_bc *bhw = bch->hw;
w6692pci *card = bch->inst.data;
w6692pci *card = bch->inst.privat;
if (card->pots == 0)
return(-ENODEV);
@ -580,7 +580,7 @@ disable_pots(bchannel_t *bch)
static int
mode_w6692(bchannel_t *bch, int bc, int protocol)
{
w6692pci *card = bch->inst.data;
w6692pci *card = bch->inst.privat;
w6692_bc *bhw = bch->hw;
@ -605,7 +605,6 @@ mode_w6692(bchannel_t *bch, int bc, int protocol)
dev_kfree_skb(bch->next_skb);
bch->next_skb = NULL;
}
discard_queue(&bch->rqueue);
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);
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_EXIM, 0);
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;
case (ISDN_PID_L1_B_64HDLC):
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_EXIM, 0);
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;
default:
mISDN_debugprint(&bch->inst, "prot not known %x", protocol);
@ -643,13 +640,21 @@ send_next(bchannel_t *bch)
W6692_fill_Bfifo(bch);
else {
bch->tx_idx = 0;
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
if (bch->next_skb) {
bch->tx_len = bch->next_skb->len;
memcpy(bch->tx_buf, bch->next_skb->data, bch->tx_len);
if (test_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
struct sk_buff *skb = bch->next_skb;
if (skb) {
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);
skb_trim(skb, 0);
queue_bch_frame(bch, CONFIRM, hh->dinfo, skb);
} else {
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");
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
}
@ -657,7 +662,6 @@ send_next(bchannel_t *bch)
bch->tx_len = 0;
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");
else {
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;
@ -739,9 +742,8 @@ W6692B_interrupt(w6692pci *card, int ch)
printk(KERN_WARNING "Bchan receive out of memory\n");
else {
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;
}
}
@ -887,7 +889,7 @@ dbusy_timer_handler(dchannel_t *dch)
int rbch, star;
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;
add_timer(&dch->dbusytimer);
return;
@ -911,7 +913,7 @@ dbusy_timer_handler(dchannel_t *dch)
/* 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 */
/******************************/
static int
w6692_l2l1B(mISDNif_t *hif, struct sk_buff *skb)
w6692_l2l1B(mISDNinstance_t *inst, struct sk_buff *skb)
{
bchannel_t *bch;
int ret = -EINVAL;
mISDN_head_t *hh;
bchannel_t *bch = container_of(inst, bchannel_t, inst);
int ret = 0;
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) ||
(hh->prim == (DL_DATA | REQUEST))) {
if (bch->next_skb) {
@ -1053,46 +1051,50 @@ w6692_l2l1B(mISDNif_t *hif, struct sk_buff *skb)
__FUNCTION__);
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)) {
test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
bch->next_skb = skb;
bch->inst.unlock(bch->inst.data);
bch->inst.unlock(bch->inst.privat);
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);
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)
&& bch->dev)
hif = &bch->dev->rport.pif;
else
hif = &bch->inst.up;
#endif
skb_trim(skb, 0);
return(if_newhead(hif, hh->prim | CONFIRM,
return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM,
hh->dinfo, skb));
}
} else if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
(hh->prim == (DL_ESTABLISH | REQUEST))) {
if (test_and_set_bit(BC_FLG_ACTIV, &bch->Flag))
ret = 0;
else {
bch->inst.lock(bch->inst.data, 0);
if (!test_and_set_bit(BC_FLG_ACTIV, &bch->Flag)) {
bch->inst.lock(bch->inst.privat, 0);
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->dev)
if_link(&bch->dev->rport.pif,
hh->prim | CONFIRM, 0, 0, NULL, 0);
#endif
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)) ||
(hh->prim == (DL_RELEASE | REQUEST)) ||
(hh->prim == (MGR_DISCONNECT | REQUEST))) {
bch->inst.lock(bch->inst.data, 0);
(hh->prim == (DL_RELEASE | REQUEST)) ||
((hh->prim == (PH_CONTROL | REQUEST) && (hh->dinfo == HW_DEACTIVATE)))) {
bch->inst.lock(bch->inst.privat, 0);
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
dev_kfree_skb(bch->next_skb);
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);
mode_w6692(bch, bch->channel, ISDN_PID_NONE);
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);
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->dev)
if_link(&bch->dev->rport.pif,
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);
}
ret = 0;
} else if (hh->prim == (PH_CONTROL | REQUEST)) {
ret = 0;
bch->inst.lock(bch->inst.data, 0);
bch->inst.lock(bch->inst.privat, 0);
if (hh->dinfo == HW_POTS_ON) {
ret = enable_pots(bch);
} 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);
} else
ret = -EINVAL;
bch->inst.unlock(bch->inst.data);
bch->inst.unlock(bch->inst.privat);
} else {
printk(KERN_WARNING "%s: unknown prim(%x)\n",
__FUNCTION__, hh->prim);
ret = -EINVAL;
}
if (!ret)
dev_kfree_skb(skb);
@ -1135,48 +1138,43 @@ w6692_l2l1B(mISDNif_t *hif, struct sk_buff *skb)
}
static int
w6692_l1hwD(mISDNif_t *hif, struct sk_buff *skb)
w6692_l1hwD(mISDNinstance_t *inst, struct sk_buff *skb)
{
dchannel_t *dch;
int ret = -EINVAL;
mISDN_head_t *hh;
dchannel_t *dch = container_of(inst, dchannel_t, inst);
int ret = 0;
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 (dch->next_skb) {
mISDN_debugprint(&dch->inst, "w6692 l2l1 next_skb exist this shouldn't happen");
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)) {
test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
dch->next_skb = skb;
dch->inst.unlock(dch->inst.data);
dch->inst.unlock(dch->inst.privat);
return(0);
} else {
dch->tx_len = skb->len;
memcpy(dch->tx_buf, skb->data, dch->tx_len);
dch->tx_idx = 0;
W6692_fill_Dfifo(dch->hw);
dch->inst.unlock(dch->inst.data);
return(if_newhead(&dch->inst.up, PH_DATA_CNF,
dch->inst.unlock(dch->inst.privat);
return(mISDN_queueup_newhead(inst, 0, PH_DATA_CNF,
hh->dinfo, skb));
}
} 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)
ph_command(dch->hw, W_L1CMD_AR8);
else if (hh->dinfo == INFO3_P10)
ph_command(dch->hw, W_L1CMD_AR10);
else
ret = -EINVAL;
dch->inst.unlock(dch->inst.data);
dch->inst.unlock(dch->inst.privat);
} 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 (dch->ph_state != W_L1IND_DRD)
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) {
ph_command(dch->hw, W_L1CMD_ECK);
} else if (hh->dinfo == HW_DEACTIVATE) {
discard_queue(&dch->rqueue);
if (dch->next_skb) {
dev_kfree_skb(dch->next_skb);
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);
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
del_timer(&dch->dbusytimer);
#ifdef FIXME
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
dchannel_sched_event(dch, D_CLEARBUSY);
#endif
} else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) {
u_char val = 0;
@ -1209,7 +1208,7 @@ w6692_l1hwD(mISDNif_t *hif, struct sk_buff *skb)
hh->dinfo);
ret = -EINVAL;
}
dch->inst.unlock(dch->inst.data);
dch->inst.unlock(dch->inst.privat);
} else {
if (dch->debug & L1_DEB_WARN)
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[0]);
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);
list_del(&card->list);
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);
break;
case MGR_UNREGLAYER | REQUEST:
if (channel == 2) {
inst->down.fdata = &card->dch;
if ((skb = create_link_skb(PH_CONTROL | REQUEST,
HW_DEACTIVATE, 0, NULL, 0))) {
if (w6692_l1hwD(&inst->down, skb))
if ((skb = create_link_skb(PH_CONTROL | REQUEST,
HW_DEACTIVATE, 0, NULL, 0))) {
if (channel == 2) {
if (w6692_l1hwD(inst, skb))
dev_kfree_skb(skb);
} else {
if (w6692_l2l1B(inst, skb))
dev_kfree_skb(skb);
}
} else {
inst->down.fdata = &card->bch[channel];
if ((skb = create_link_skb(MGR_DISCONNECT | REQUEST,
0, 0, NULL, 0))) {
if (w6692_l2l1B(&inst->down, skb))
dev_kfree_skb(skb);
}
}
w6692.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
} else
printk(KERN_WARNING "no SKB in %s MGR_UNREGLAYER | REQUEST\n", __FUNCTION__);
w6692.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
break;
case MGR_CLRSTPARA | INDICATION:
@ -1361,33 +1354,18 @@ w6692_manager(void *data, u_int prim, void *arg) {
w6692.refcnt--;
}
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:
if ((channel!=2) && (inst->pid.global == 2)) {
inst->down.fdata = &card->bch[channel];
if ((skb = create_link_skb(PH_ACTIVATE | REQUEST,
0, 0, NULL, 0))) {
if (w6692_l2l1B(&inst->down, skb))
if (w6692_l2l1B(inst, skb))
dev_kfree_skb(skb);
}
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);
else
if_link(&inst->up, PH_ACTIVATE | INDICATION,
mISDN_queue_data(inst, FLG_MSG_UP, PH_ACTIVATE | INDICATION,
0, 0, NULL, 0);
}
break;
@ -1425,14 +1403,14 @@ static int __devinit setup_instance(w6692pci *card)
card->dch.inst.unlock = unlock_dev;
card->dch.inst.pid.layermask = ISDN_LAYER(0);
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);
mISDN_set_dchannel_pid(&pid, protocol[w6692_cnt], layermask[w6692_cnt]);
mISDN_init_dch(&card->dch);
card->dch.hw = card;
for (i=0; i<2; 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.lock = lock_dev;
card->bch[i].inst.unlock = unlock_dev;