- common HW layer channel model for B and D channel
* reduce duplicated code * not finished and tested for all drivers
This commit is contained in:
parent
e1b97ac317
commit
0913082112
|
@ -69,7 +69,7 @@ hfcmulti-objs := hfc_multi.o
|
|||
xhfc-objs := xhfc_su.o xhfc_pci2pi.o
|
||||
mISDN_isac-objs := isac.o arcofi.o
|
||||
mISDN_core-objs := core.o stack.o udevice.o helper.o debug.o fsm.o \
|
||||
dchannel.o bchannel.o l3helper.o \
|
||||
channel.o l3helper.o \
|
||||
sysfs_obj.o sysfs_inst.o sysfs_st.o
|
||||
ifdef CONFIG_MISDN_MEMDEBUG
|
||||
mISDN_core-objs += memdbg.o
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "dchannel.h"
|
||||
#include "channel.h"
|
||||
#include "layer1.h"
|
||||
#include "isac.h"
|
||||
#include "arcofi.h"
|
||||
|
@ -18,10 +18,10 @@
|
|||
#define ARCOFI_TIMER_VALUE 20
|
||||
|
||||
static void
|
||||
add_arcofi_timer(dchannel_t *dch) {
|
||||
add_arcofi_timer(channel_t *dch) {
|
||||
isac_chip_t *isac = dch->hw;
|
||||
|
||||
if (test_and_set_bit(FLG_ARCOFI_TIMER, &dch->DFlags)) {
|
||||
if (test_and_set_bit(FLG_ARCOFI_TIMER, &dch->Flags)) {
|
||||
del_timer(&isac->arcofitimer);
|
||||
}
|
||||
init_timer(&isac->arcofitimer);
|
||||
|
@ -30,7 +30,7 @@ add_arcofi_timer(dchannel_t *dch) {
|
|||
}
|
||||
|
||||
static void
|
||||
send_arcofi(dchannel_t *dch) {
|
||||
send_arcofi(channel_t *dch) {
|
||||
u_char val;
|
||||
isac_chip_t *isac = dch->hw;
|
||||
|
||||
|
@ -54,7 +54,7 @@ send_arcofi(dchannel_t *dch) {
|
|||
}
|
||||
|
||||
int
|
||||
arcofi_fsm(dchannel_t *dch, int event, void *data) {
|
||||
arcofi_fsm(channel_t *dch, int event, void *data) {
|
||||
isac_chip_t *isac = dch->hw;
|
||||
|
||||
if (dch->debug & L1_DEB_MONITOR) {
|
||||
|
@ -62,7 +62,7 @@ arcofi_fsm(dchannel_t *dch, int event, void *data) {
|
|||
}
|
||||
if (event == ARCOFI_TIMEOUT) {
|
||||
isac->arcofi_state = ARCOFI_NOP;
|
||||
test_and_set_bit(FLG_ARCOFI_ERROR, &dch->DFlags);
|
||||
test_and_set_bit(FLG_ARCOFI_ERROR, &dch->Flags);
|
||||
wake_up(&isac->arcofi_wait);
|
||||
return(1);
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ arcofi_fsm(dchannel_t *dch, int event, void *data) {
|
|||
isac->arcofi_list->next;
|
||||
send_arcofi(dch);
|
||||
} else {
|
||||
if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->DFlags)) {
|
||||
if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->Flags)) {
|
||||
del_timer(&isac->arcofitimer);
|
||||
}
|
||||
isac->arcofi_state = ARCOFI_NOP;
|
||||
|
@ -109,7 +109,7 @@ arcofi_fsm(dchannel_t *dch, int event, void *data) {
|
|||
isac->arcofi_state = ARCOFI_TRANSMIT;
|
||||
send_arcofi(dch);
|
||||
} else {
|
||||
if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->DFlags)) {
|
||||
if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->Flags)) {
|
||||
del_timer(&isac->arcofitimer);
|
||||
}
|
||||
isac->arcofi_state = ARCOFI_NOP;
|
||||
|
@ -125,21 +125,21 @@ arcofi_fsm(dchannel_t *dch, int event, void *data) {
|
|||
}
|
||||
|
||||
static void
|
||||
arcofi_timer(dchannel_t *dch) {
|
||||
arcofi_timer(channel_t *dch) {
|
||||
arcofi_fsm(dch, ARCOFI_TIMEOUT, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
clear_arcofi(dchannel_t *dch) {
|
||||
clear_arcofi(channel_t *dch) {
|
||||
isac_chip_t *isac = dch->hw;
|
||||
|
||||
if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->DFlags)) {
|
||||
if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->Flags)) {
|
||||
del_timer(&isac->arcofitimer);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
init_arcofi(dchannel_t *dch) {
|
||||
init_arcofi(channel_t *dch) {
|
||||
isac_chip_t *isac = dch->hw;
|
||||
|
||||
isac->arcofitimer.function = (void *) arcofi_timer;
|
||||
|
|
|
@ -27,6 +27,6 @@ struct arcofi_msg {
|
|||
u_char msg[10];
|
||||
};
|
||||
|
||||
extern int arcofi_fsm(dchannel_t *, int, void *);
|
||||
extern void init_arcofi(dchannel_t *);
|
||||
extern void clear_arcofi(dchannel_t *);
|
||||
extern int arcofi_fsm(channel_t *, int, void *);
|
||||
extern void init_arcofi(channel_t *);
|
||||
extern void clear_arcofi(channel_t *);
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
#include <linux/isapnp.h>
|
||||
#endif
|
||||
#include <linux/delay.h>
|
||||
#include "dchannel.h"
|
||||
#include "bchannel.h"
|
||||
#include "channel.h"
|
||||
#include "isac.h"
|
||||
#include "layer1.h"
|
||||
#include "debug.h"
|
||||
|
@ -144,8 +143,8 @@ typedef struct _fritzpnppci {
|
|||
spinlock_t lock;
|
||||
isac_chip_t isac;
|
||||
hdlc_hw_t hdlc[2];
|
||||
dchannel_t dch;
|
||||
bchannel_t bch[2];
|
||||
channel_t dch;
|
||||
channel_t bch[2];
|
||||
u_char ctrlreg;
|
||||
} fritzpnppci;
|
||||
|
||||
|
@ -235,11 +234,11 @@ fcpci2_write_isac_fifo(void *fc, unsigned char * data, int size)
|
|||
}
|
||||
|
||||
static inline
|
||||
bchannel_t *Sel_BCS(fritzpnppci *fc, int channel)
|
||||
channel_t *Sel_BCS(fritzpnppci *fc, int channel)
|
||||
{
|
||||
if (fc->bch[0].protocol && (fc->bch[0].channel == channel))
|
||||
if (test_bit(FLG_ACTIVE, &fc->bch[0].Flags) && (fc->bch[0].channel == channel))
|
||||
return(&fc->bch[0]);
|
||||
else if (fc->bch[1].protocol && (fc->bch[1].channel == channel))
|
||||
else if (test_bit(FLG_ACTIVE, &fc->bch[1].Flags) && (fc->bch[1].channel == channel))
|
||||
return(&fc->bch[1]);
|
||||
else
|
||||
return(NULL);
|
||||
|
@ -272,7 +271,7 @@ __write_ctrl_pciv2(fritzpnppci *fc, hdlc_hw_t *hdlc, int channel) {
|
|||
}
|
||||
|
||||
void
|
||||
write_ctrl(bchannel_t *bch, int which) {
|
||||
write_ctrl(channel_t *bch, int which) {
|
||||
fritzpnppci *fc = bch->inst.privat;
|
||||
hdlc_hw_t *hdlc = bch->hw;
|
||||
|
||||
|
@ -349,47 +348,49 @@ disable_hwirq(fritzpnppci *fc)
|
|||
}
|
||||
|
||||
static int
|
||||
modehdlc(bchannel_t *bch, int bc, int protocol)
|
||||
modehdlc(channel_t *bch, int bc, int protocol)
|
||||
{
|
||||
hdlc_hw_t *hdlc = bch->hw;
|
||||
|
||||
if (bch->debug & L1_DEB_HSCX)
|
||||
mISDN_debugprint(&bch->inst, "hdlc %c protocol %x-->%x ch %d-->%d",
|
||||
'A' + bch->channel, bch->protocol, protocol, bch->channel, bc);
|
||||
'A' + bch->channel, bch->state, protocol, bch->channel, bc);
|
||||
if ((protocol != -1) && (bc != bch->channel))
|
||||
printk(KERN_WARNING "%s: fritzcard mismatch channel(%d/%d)\n", __FUNCTION__, bch->channel, bc);
|
||||
hdlc->ctrl.ctrl = 0;
|
||||
switch (protocol) {
|
||||
case (-1): /* used for init */
|
||||
bch->protocol = -1;
|
||||
bch->state = -1;
|
||||
bch->channel = bc;
|
||||
case (ISDN_PID_NONE):
|
||||
if (bch->protocol == ISDN_PID_NONE)
|
||||
if (bch->state == ISDN_PID_NONE)
|
||||
break;
|
||||
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
|
||||
hdlc->ctrl.sr.mode = HDLC_MODE_TRANS;
|
||||
write_ctrl(bch, 5);
|
||||
bch->protocol = ISDN_PID_NONE;
|
||||
bch->state = ISDN_PID_NONE;
|
||||
test_and_clear_bit(FLG_HDLC, &bch->Flags);
|
||||
test_and_clear_bit(FLG_TRANSPARENT, &bch->Flags);
|
||||
break;
|
||||
case (ISDN_PID_L1_B_64TRANS):
|
||||
bch->protocol = protocol;
|
||||
bch->state = protocol;
|
||||
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
|
||||
hdlc->ctrl.sr.mode = HDLC_MODE_TRANS;
|
||||
write_ctrl(bch, 5);
|
||||
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
|
||||
write_ctrl(bch, 1);
|
||||
hdlc->ctrl.sr.cmd = 0;
|
||||
// FIXME bch_sched_event(bch, B_XMTBUFREADY);
|
||||
test_and_set_bit(FLG_TRANSPARENT, &bch->Flags);
|
||||
break;
|
||||
case (ISDN_PID_L1_B_64HDLC):
|
||||
bch->protocol = protocol;
|
||||
bch->state = protocol;
|
||||
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
|
||||
hdlc->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
|
||||
write_ctrl(bch, 5);
|
||||
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
|
||||
write_ctrl(bch, 1);
|
||||
hdlc->ctrl.sr.cmd = 0;
|
||||
// FIXME bch_sched_event(bch, B_XMTBUFREADY);
|
||||
test_and_set_bit(FLG_HDLC, &bch->Flags);
|
||||
break;
|
||||
default:
|
||||
mISDN_debugprint(&bch->inst, "prot not known %x", protocol);
|
||||
|
@ -399,7 +400,7 @@ modehdlc(bchannel_t *bch, int bc, int protocol)
|
|||
}
|
||||
|
||||
static void
|
||||
hdlc_empty_fifo(bchannel_t *bch, int count)
|
||||
hdlc_empty_fifo(channel_t *bch, int count)
|
||||
{
|
||||
register u_int *ptr;
|
||||
u_char *p;
|
||||
|
@ -409,14 +410,20 @@ hdlc_empty_fifo(bchannel_t *bch, int count)
|
|||
|
||||
if ((fc->dch.debug & L1_DEB_HSCX) && !(fc->dch.debug & L1_DEB_HSCX_FIFO))
|
||||
mISDN_debugprint(&bch->inst, "hdlc_empty_fifo %d", count);
|
||||
if (bch->rx_idx + count > MAX_DATA_MEM) {
|
||||
if (fc->dch.debug & L1_DEB_WARN)
|
||||
mISDN_debugprint(&bch->inst, "hdlc_empty_fifo: incoming packet too large");
|
||||
if (!bch->rx_skb) {
|
||||
if (!(bch->rx_skb = alloc_stack_skb(bch->maxlen, bch->up_headerlen))) {
|
||||
printk(KERN_WARNING "mISDN: B receive out of memory\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((bch->rx_skb->len + count) > bch->maxlen) {
|
||||
if (bch->debug & L1_DEB_WARN)
|
||||
mISDN_debugprint(&bch->inst, "hdlc_empty_fifo overrun %d",
|
||||
bch->rx_skb->len + count);
|
||||
return;
|
||||
}
|
||||
p = bch->rx_buf + bch->rx_idx;
|
||||
p = skb_put(bch->rx_skb, count);
|
||||
ptr = (u_int *)p;
|
||||
bch->rx_idx += count;
|
||||
if (fc->type == AVM_FRITZ_PCIV2) {
|
||||
while (cnt < count) {
|
||||
#ifdef __powerpc__
|
||||
|
@ -452,21 +459,21 @@ hdlc_empty_fifo(bchannel_t *bch, int count)
|
|||
}
|
||||
}
|
||||
if (fc->dch.debug & L1_DEB_HSCX_FIFO) {
|
||||
char *t = bch->blog;
|
||||
char *t = bch->log;
|
||||
|
||||
if (fc->type == AVM_FRITZ_PNP)
|
||||
p = (u_char *) ptr;
|
||||
t += sprintf(t, "hdlc_empty_fifo %c cnt %d",
|
||||
bch->channel ? 'B' : 'A', count);
|
||||
mISDN_QuickHex(t, p, count);
|
||||
mISDN_debugprint(&bch->inst, bch->blog);
|
||||
mISDN_debugprint(&bch->inst, bch->log);
|
||||
}
|
||||
}
|
||||
|
||||
#define HDLC_FIFO_SIZE 32
|
||||
|
||||
static void
|
||||
hdlc_fill_fifo(bchannel_t *bch)
|
||||
hdlc_fill_fifo(channel_t *bch)
|
||||
{
|
||||
fritzpnppci *fc = bch->inst.privat;
|
||||
hdlc_hw_t *hdlc = bch->hw;
|
||||
|
@ -476,15 +483,17 @@ hdlc_fill_fifo(bchannel_t *bch)
|
|||
|
||||
if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
|
||||
mISDN_debugprint(&bch->inst, "%s", __FUNCTION__);
|
||||
count = bch->tx_len - bch->tx_idx;
|
||||
if (!bch->tx_skb)
|
||||
return;
|
||||
count = bch->tx_skb->len - bch->tx_idx;
|
||||
if (count <= 0)
|
||||
return;
|
||||
p = bch->tx_buf + bch->tx_idx;
|
||||
p = bch->tx_skb->data + bch->tx_idx;
|
||||
hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME;
|
||||
if (count > HDLC_FIFO_SIZE) {
|
||||
count = HDLC_FIFO_SIZE;
|
||||
} else {
|
||||
if (bch->protocol != ISDN_PID_L1_B_64TRANS)
|
||||
if (test_bit(FLG_HDLC, &bch->Flags))
|
||||
hdlc->ctrl.sr.cmd |= HDLC_CMD_XME;
|
||||
}
|
||||
if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
|
||||
|
@ -529,51 +538,49 @@ hdlc_fill_fifo(bchannel_t *bch)
|
|||
}
|
||||
}
|
||||
if (bch->debug & L1_DEB_HSCX_FIFO) {
|
||||
char *t = bch->blog;
|
||||
char *t = bch->log;
|
||||
|
||||
if (fc->type == AVM_FRITZ_PNP)
|
||||
p = (u_char *) ptr;
|
||||
t += sprintf(t, "hdlc_fill_fifo %c cnt %d",
|
||||
bch->channel ? 'B' : 'A', count);
|
||||
mISDN_QuickHex(t, p, count);
|
||||
mISDN_debugprint(&bch->inst, bch->blog);
|
||||
mISDN_debugprint(&bch->inst, bch->log);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
HDLC_irq_xpr(bchannel_t *bch)
|
||||
HDLC_irq_xpr(channel_t *bch)
|
||||
{
|
||||
if (bch->tx_idx < bch->tx_len)
|
||||
if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len)
|
||||
hdlc_fill_fifo(bch);
|
||||
else {
|
||||
if (bch->tx_skb)
|
||||
dev_kfree_skb(bch->tx_skb);
|
||||
bch->tx_idx = 0;
|
||||
if (test_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
|
||||
struct sk_buff *skb = bch->next_skb;
|
||||
mISDN_head_t *hh;
|
||||
if (skb) {
|
||||
if (test_bit(FLG_TX_NEXT, &bch->Flags)) {
|
||||
bch->tx_skb = bch->next_skb;
|
||||
if (bch->tx_skb) {
|
||||
mISDN_head_t *hh = mISDN_HEAD_P(bch->tx_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);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &bch->Flags);
|
||||
queue_ch_frame(bch, CONFIRM, hh->dinfo, NULL);
|
||||
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);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &bch->Flags);
|
||||
test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
|
||||
}
|
||||
} else {
|
||||
bch->tx_len = 0;
|
||||
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
|
||||
bch->tx_skb = NULL;
|
||||
test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
HDLC_irq(bchannel_t *bch, u_int stat)
|
||||
HDLC_irq(channel_t *bch, u_int stat)
|
||||
{
|
||||
int len;
|
||||
struct sk_buff *skb;
|
||||
|
@ -592,42 +599,58 @@ HDLC_irq(bchannel_t *bch, u_int stat)
|
|||
write_ctrl(bch, 1);
|
||||
hdlc->ctrl.sr.cmd &= ~HDLC_CMD_RRS;
|
||||
write_ctrl(bch, 1);
|
||||
bch->rx_idx = 0;
|
||||
if (bch->rx_skb)
|
||||
skb_trim(bch->rx_skb, 0);
|
||||
} else {
|
||||
if (!(len = (stat & HDLC_STAT_RML_MASK)>>8))
|
||||
len = 32;
|
||||
hdlc_empty_fifo(bch, len);
|
||||
if ((stat & HDLC_STAT_RME) || (bch->protocol == ISDN_PID_L1_B_64TRANS)) {
|
||||
if (!bch->rx_skb)
|
||||
goto handle_tx;
|
||||
if ((stat & HDLC_STAT_RME) || test_bit(FLG_TRANSPARENT, &bch->Flags)) {
|
||||
if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) ||
|
||||
(bch->protocol == ISDN_PID_L1_B_64TRANS)) {
|
||||
if (!(skb = alloc_stack_skb(bch->rx_idx, bch->up_headerlen)))
|
||||
printk(KERN_WARNING "HDLC: receive out of memory\n");
|
||||
else {
|
||||
memcpy(skb_put(skb, bch->rx_idx),
|
||||
bch->rx_buf, bch->rx_idx);
|
||||
queue_bch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
|
||||
test_bit(FLG_TRANSPARENT, &bch->Flags)) {
|
||||
if (bch->rx_skb->len < MISDN_COPY_SIZE) {
|
||||
skb = alloc_stack_skb(bch->rx_skb->len, bch->up_headerlen);
|
||||
if (skb) {
|
||||
memcpy(skb_put(skb, bch->rx_skb->len),
|
||||
bch->rx_skb->data, bch->rx_skb->len);
|
||||
skb_trim(bch->rx_skb, 0);
|
||||
} else {
|
||||
skb = bch->rx_skb;
|
||||
bch->rx_skb = NULL;
|
||||
}
|
||||
} else {
|
||||
skb = bch->rx_skb;
|
||||
bch->rx_skb = NULL;
|
||||
}
|
||||
bch->rx_idx = 0;
|
||||
queue_ch_frame(bch, INDICATION, MISDN_ID_ANY, skb);
|
||||
} else {
|
||||
if (bch->debug & L1_DEB_HSCX)
|
||||
mISDN_debugprint(&bch->inst, "invalid frame");
|
||||
else
|
||||
mISDN_debugprint(&bch->inst, "ch%d invalid frame %#x", bch->channel, stat);
|
||||
bch->rx_idx = 0;
|
||||
skb_trim(bch->rx_skb, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
handle_tx:
|
||||
if (stat & HDLC_INT_XDU) {
|
||||
/* Here we lost an TX interrupt, so
|
||||
* restart transmitting the whole frame on HDLC
|
||||
* in transparent mode we send the next data
|
||||
*/
|
||||
if (bch->debug & L1_DEB_WARN)
|
||||
mISDN_debugprint(&bch->inst, "ch%d XDU tx_len(%d) tx_idx(%d) Flag(%lx)",
|
||||
bch->channel, bch->tx_len, bch->tx_idx, bch->Flag);
|
||||
if (bch->tx_len) {
|
||||
if (bch->protocol != ISDN_PID_L1_B_64TRANS)
|
||||
if (bch->debug & L1_DEB_WARN) {
|
||||
if (bch->tx_skb)
|
||||
mISDN_debugprint(&bch->inst, "ch%d XDU tx_len(%d) tx_idx(%d) Flags(%lx)",
|
||||
bch->channel, bch->tx_skb->len, bch->tx_idx, bch->Flags);
|
||||
else
|
||||
mISDN_debugprint(&bch->inst, "ch%d XDU no tx_skb Flags(%lx)",
|
||||
bch->channel, bch->Flags);
|
||||
}
|
||||
if (bch->tx_skb && bch->tx_skb->len) {
|
||||
if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
|
||||
bch->tx_idx = 0;
|
||||
}
|
||||
hdlc->ctrl.sr.xml = 0;
|
||||
|
@ -644,7 +667,7 @@ static inline void
|
|||
HDLC_irq_main(fritzpnppci *fc)
|
||||
{
|
||||
u_int stat;
|
||||
bchannel_t *bch;
|
||||
channel_t *bch;
|
||||
|
||||
stat = read_status(fc, 0);
|
||||
if (stat & HDLC_INT_MASK) {
|
||||
|
@ -736,47 +759,25 @@ avm_fritzv2_interrupt(int intno, void *dev_id, struct pt_regs *regs)
|
|||
static int
|
||||
hdlc_down(mISDNinstance_t *inst, struct sk_buff *skb)
|
||||
{
|
||||
bchannel_t *bch;
|
||||
channel_t *bch;
|
||||
int ret = 0;
|
||||
mISDN_head_t *hh;
|
||||
mISDN_head_t *hh = mISDN_HEAD_P(skb);
|
||||
u_long flags;
|
||||
|
||||
hh = mISDN_HEAD_P(skb);
|
||||
bch = container_of(inst, bchannel_t, inst);
|
||||
if ((hh->prim == PH_DATA_REQ) ||
|
||||
(hh->prim == (DL_DATA | REQUEST))) {
|
||||
if (skb->len <= 0) {
|
||||
printk(KERN_WARNING "%s: skb too small\n", __FUNCTION__);
|
||||
return(-EINVAL);
|
||||
}
|
||||
if (skb->len > MAX_DATA_MEM) {
|
||||
printk(KERN_WARNING "%s: skb too large\n", __FUNCTION__);
|
||||
return(-EINVAL);
|
||||
}
|
||||
bch = container_of(inst, channel_t, inst);
|
||||
if ((hh->prim == PH_DATA_REQ) || (hh->prim == DL_DATA_REQ)) {
|
||||
spin_lock_irqsave(inst->hwlock, flags);
|
||||
if (bch->next_skb) {
|
||||
mISDN_debugprint(&bch->inst, " l2l1 next_skb exist this shouldn't happen");
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
return(-EBUSY);
|
||||
}
|
||||
if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
|
||||
test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
|
||||
bch->next_skb = skb;
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
return(0);
|
||||
} else {
|
||||
bch->tx_len = skb->len;
|
||||
memcpy(bch->tx_buf, skb->data, bch->tx_len);
|
||||
bch->tx_idx = 0;
|
||||
ret = channel_senddata(bch, hh->dinfo, skb);
|
||||
if (ret > 0) { /* direct TX */
|
||||
hdlc_fill_fifo(bch);
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
skb_trim(skb, 0);
|
||||
return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM,
|
||||
hh->dinfo, skb));
|
||||
ret = 0;
|
||||
}
|
||||
} else if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
return(ret);
|
||||
}
|
||||
if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
|
||||
(hh->prim == (DL_ESTABLISH | REQUEST))) {
|
||||
if (!test_and_set_bit(BC_FLG_ACTIV, &bch->Flag)) {
|
||||
if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) {
|
||||
spin_lock_irqsave(inst->hwlock, flags);
|
||||
ret = modehdlc(bch, bch->channel,
|
||||
bch->inst.pid.protocol[1]);
|
||||
|
@ -788,13 +789,18 @@ hdlc_down(mISDNinstance_t *inst, struct sk_buff *skb)
|
|||
(hh->prim == (DL_RELEASE | REQUEST)) ||
|
||||
((hh->prim == (PH_CONTROL | REQUEST) && (hh->dinfo == HW_DEACTIVATE)))) {
|
||||
spin_lock_irqsave(inst->hwlock, flags);
|
||||
if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
|
||||
if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) {
|
||||
dev_kfree_skb(bch->next_skb);
|
||||
bch->next_skb = NULL;
|
||||
}
|
||||
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
|
||||
if (bch->tx_skb) {
|
||||
dev_kfree_skb(bch->tx_skb);
|
||||
bch->tx_skb = NULL;
|
||||
bch->tx_idx = 0;
|
||||
}
|
||||
test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
|
||||
modehdlc(bch, bch->channel, 0);
|
||||
test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag);
|
||||
test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
skb_trim(skb, 0);
|
||||
if (hh->prim != (PH_CONTROL | REQUEST))
|
||||
|
@ -1026,9 +1032,9 @@ release_card(fritzpnppci *card)
|
|||
free_irq(card->irq, card);
|
||||
spin_lock_irqsave(&card->lock, flags);
|
||||
release_region(card->addr, 32);
|
||||
mISDN_free_bch(&card->bch[1]);
|
||||
mISDN_free_bch(&card->bch[0]);
|
||||
mISDN_free_dch(&card->dch);
|
||||
mISDN_freechannel(&card->bch[1]);
|
||||
mISDN_freechannel(&card->bch[0]);
|
||||
mISDN_freechannel(&card->dch);
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
fritz.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
spin_lock_irqsave(&fritz.lock, flags);
|
||||
|
@ -1088,9 +1094,9 @@ fritz_manager(void *data, u_int prim, void *arg) {
|
|||
switch(prim) {
|
||||
case MGR_REGLAYER | CONFIRM:
|
||||
if (channel == 2)
|
||||
dch_set_para(&card->dch, &inst->st->para);
|
||||
mISDN_setpara(&card->dch, &inst->st->para);
|
||||
else
|
||||
bch_set_para(&card->bch[channel], &inst->st->para);
|
||||
mISDN_setpara(&card->bch[channel], &inst->st->para);
|
||||
break;
|
||||
case MGR_UNREGLAYER | REQUEST:
|
||||
if ((skb = create_link_skb(PH_CONTROL | REQUEST,
|
||||
|
@ -1110,9 +1116,9 @@ fritz_manager(void *data, u_int prim, void *arg) {
|
|||
arg = NULL;
|
||||
case MGR_ADDSTPARA | INDICATION:
|
||||
if (channel == 2)
|
||||
dch_set_para(&card->dch, arg);
|
||||
mISDN_setpara(&card->dch, arg);
|
||||
else
|
||||
bch_set_para(&card->bch[channel], arg);
|
||||
mISDN_setpara(&card->bch[channel], arg);
|
||||
break;
|
||||
case MGR_RELEASE | INDICATION:
|
||||
if (channel == 2) {
|
||||
|
@ -1174,7 +1180,7 @@ static int __devinit setup_instance(fritzpnppci *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);
|
||||
mISDN_initchannel(&card->dch, MSK_INIT_DCHANNEL, MAX_DFRAME_LEN_L1);
|
||||
for (i=0; i<2; i++) {
|
||||
card->bch[i].channel = i;
|
||||
mISDN_init_instance(&card->bch[i].inst, &fritz, card, hdlc_down);
|
||||
|
@ -1183,16 +1189,16 @@ static int __devinit setup_instance(fritzpnppci *card)
|
|||
card->bch[i].inst.class_dev.dev = dev;
|
||||
card->bch[i].debug = debug;
|
||||
sprintf(card->bch[i].inst.name, "%s B%d", card->dch.inst.name, i+1);
|
||||
mISDN_init_bch(&card->bch[i]);
|
||||
mISDN_initchannel(&card->bch[i], MSK_INIT_BCHANNEL, MAX_DATA_MEM);
|
||||
card->bch[i].hw = &card->hdlc[i];
|
||||
}
|
||||
printk(KERN_DEBUG "fritz card %p dch %p bch1 %p bch2 %p\n",
|
||||
card, &card->dch, &card->bch[0], &card->bch[1]);
|
||||
err = setup_fritz(card);
|
||||
if (err) {
|
||||
mISDN_free_dch(&card->dch);
|
||||
mISDN_free_bch(&card->bch[1]);
|
||||
mISDN_free_bch(&card->bch[0]);
|
||||
mISDN_freechannel(&card->dch);
|
||||
mISDN_freechannel(&card->bch[1]);
|
||||
mISDN_freechannel(&card->bch[0]);
|
||||
spin_lock_irqsave(&fritz.lock, flags);
|
||||
list_del(&card->list);
|
||||
spin_unlock_irqrestore(&fritz.lock, flags);
|
||||
|
|
|
@ -1,155 +0,0 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Author Karsten Keil (keil@isdn4linux.de)
|
||||
*
|
||||
* This file is (c) under GNU PUBLIC LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mISDNif.h>
|
||||
#include "layer1.h"
|
||||
#include "bchannel.h"
|
||||
#include "helper.h"
|
||||
|
||||
#ifdef OBSOLETE
|
||||
static void
|
||||
bchannel_bh(bchannel_t *bch)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
u_int pr;
|
||||
int ret;
|
||||
mISDN_head_t *hh;
|
||||
|
||||
if (!bch)
|
||||
return;
|
||||
#if 0
|
||||
printk(KERN_DEBUG "%s: event %x\n", __FUNCTION__, bch->event);
|
||||
if (bch->dev)
|
||||
printk(KERN_DEBUG "%s: rpflg(%x) wpflg(%x)\n", __FUNCTION__,
|
||||
bch->dev->rport.Flag, bch->dev->wport.Flag);
|
||||
#endif
|
||||
if (test_and_clear_bit(B_XMTBUFREADY, &bch->event)) {
|
||||
skb = bch->next_skb;
|
||||
if (skb) {
|
||||
hh = mISDN_HEAD_P(skb);
|
||||
bch->next_skb = NULL;
|
||||
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
|
||||
pr = DL_DATA | CONFIRM;
|
||||
else
|
||||
pr = PH_DATA | CONFIRM;
|
||||
#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
|
||||
if (mISDN_queueup_newhead(&bch->inst, 0, pr, hh->dinfo, skb))
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
if (test_and_clear_bit(B_RCVBUFREADY, &bch->event)) {
|
||||
#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
|
||||
while ((skb = skb_dequeue(&bch->rqueue))) {
|
||||
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
|
||||
pr = DL_DATA | INDICATION;
|
||||
else
|
||||
pr = PH_DATA | INDICATION;
|
||||
ret = mISDN_queueup_newhead(&bch->inst, 0, pr, MISDN_ID_ANY, skb);
|
||||
if (ret < 0) {
|
||||
printk(KERN_WARNING "%s: deliver err %d\n",
|
||||
__FUNCTION__, ret);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bch->hw_bh)
|
||||
bch->hw_bh(bch);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
mISDN_init_bch(bchannel_t *bch) {
|
||||
int devtyp = mISDN_RAW_DEVICE;
|
||||
|
||||
if (!(bch->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
|
||||
printk(KERN_WARNING
|
||||
"mISDN: No memory for blog\n");
|
||||
return(-ENOMEM);
|
||||
}
|
||||
if (!(bch->rx_buf = kmalloc(MAX_DATA_MEM, GFP_ATOMIC))) {
|
||||
printk(KERN_WARNING
|
||||
"mISDN: No memory for bchannel rx_buf\n");
|
||||
kfree(bch->blog);
|
||||
bch->blog = NULL;
|
||||
return (-ENOMEM);
|
||||
}
|
||||
if (!(bch->tx_buf = kmalloc(MAX_DATA_MEM, GFP_ATOMIC))) {
|
||||
printk(KERN_WARNING
|
||||
"mISDN: No memory for bchannel tx_buf\n");
|
||||
kfree(bch->blog);
|
||||
bch->blog = NULL;
|
||||
kfree(bch->rx_buf);
|
||||
bch->rx_buf = NULL;
|
||||
return (-ENOMEM);
|
||||
}
|
||||
#ifdef OBSOLETE
|
||||
skb_queue_head_init(&bch->rqueue);
|
||||
bch->event = 0;
|
||||
INIT_WORK(&bch->work, (void *)(void *)bchannel_bh, bch);
|
||||
#endif
|
||||
bch->next_skb = NULL;
|
||||
bch->Flag = 0;
|
||||
bch->rx_idx = 0;
|
||||
bch->tx_len = 0;
|
||||
bch->tx_idx = 0;
|
||||
bch->hw_bh = NULL;
|
||||
if (!bch->dev) {
|
||||
if (bch->inst.obj->ctrl(&bch->dev, MGR_GETDEVICE | REQUEST,
|
||||
&devtyp)) {
|
||||
printk(KERN_WARNING
|
||||
"mISDN: no raw device for bchannel\n");
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
mISDN_free_bch(bchannel_t *bch) {
|
||||
#ifdef OBSOLETE
|
||||
#ifdef HAS_WORKQUEUE
|
||||
if (bch->work.pending)
|
||||
printk(KERN_ERR "mISDN_free_bch work:(%lx)\n", bch->work.pending);
|
||||
#else
|
||||
if (bch->work.sync)
|
||||
printk(KERN_ERR "mISDN_free_bch work:(%lx)\n", bch->work.sync);
|
||||
#endif
|
||||
discard_queue(&bch->rqueue);
|
||||
#endif
|
||||
kfree(bch->blog);
|
||||
bch->blog = NULL;
|
||||
kfree(bch->rx_buf);
|
||||
bch->rx_buf = NULL;
|
||||
kfree(bch->tx_buf);
|
||||
bch->tx_buf = NULL;
|
||||
if (bch->next_skb) {
|
||||
dev_kfree_skb(bch->next_skb);
|
||||
bch->next_skb = NULL;
|
||||
}
|
||||
if (bch->inst.obj->ctrl(bch->dev, MGR_DELDEVICE | REQUEST, NULL)) {
|
||||
printk(KERN_WARNING
|
||||
"mISDN: del raw device error\n");
|
||||
} else
|
||||
bch->dev = NULL;
|
||||
return(0);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(mISDN_init_bch);
|
||||
EXPORT_SYMBOL(mISDN_free_bch);
|
|
@ -1,120 +0,0 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Basic declarations, defines for Bchannel hardware
|
||||
*
|
||||
* 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>
|
||||
#else
|
||||
#include <linux/tqueue.h>
|
||||
#endif
|
||||
#include <linux/smp.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/timer.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/skbuff.h>
|
||||
#ifdef MISDN_MEMDEBUG
|
||||
#include "memdbg.h"
|
||||
#endif
|
||||
#include "helper.h"
|
||||
|
||||
#define MAX_BLOG_SPACE 256
|
||||
|
||||
#define BC_FLG_INIT 1
|
||||
#define BC_FLG_ACTIV 2
|
||||
#define BC_FLG_TX_BUSY 3
|
||||
#define BC_FLG_NOFRAME 4
|
||||
#define BC_FLG_HALF 5
|
||||
#define BC_FLG_EMPTY 6
|
||||
#define BC_FLG_ORIG 7
|
||||
#define BC_FLG_DLEETX 8
|
||||
#define BC_FLG_LASTDLE 9
|
||||
#define BC_FLG_FIRST 10
|
||||
#define BC_FLG_LASTDATA 11
|
||||
#define BC_FLG_NMD_DATA 12
|
||||
#define BC_FLG_FTI_RUN 13
|
||||
#define BC_FLG_LL_OK 14
|
||||
#define BC_FLG_LL_CONN 15
|
||||
#define BC_FLG_TX_NEXT 16
|
||||
#define BC_FLG_DTMFSEND 17
|
||||
|
||||
typedef struct _bchannel_t {
|
||||
int channel;
|
||||
int protocol;
|
||||
u_long Flag;
|
||||
int debug;
|
||||
mISDNinstance_t inst;
|
||||
mISDNdevice_t *dev;
|
||||
void *hw;
|
||||
u_char (*Read_Reg)(void *, int, u_char);
|
||||
void (*Write_Reg)(void *, int, u_char, u_char);
|
||||
struct sk_buff *next_skb;
|
||||
u_char *tx_buf;
|
||||
int tx_idx;
|
||||
int tx_len;
|
||||
u_char *rx_buf;
|
||||
int rx_idx;
|
||||
u_char *blog;
|
||||
u_char *conmsg;
|
||||
struct timer_list transbusy;
|
||||
#ifdef OBSOLETE
|
||||
struct sk_buff_head rqueue; /* B-Channel receive Queue */
|
||||
struct work_struct work;
|
||||
u_long event;
|
||||
#endif
|
||||
void (*hw_bh) (struct _bchannel_t *);
|
||||
int maxdatasize;
|
||||
int up_headerlen;
|
||||
int err_crc;
|
||||
int err_tx;
|
||||
int err_rdo;
|
||||
int err_inv;
|
||||
} bchannel_t;
|
||||
|
||||
extern int mISDN_init_bch(bchannel_t *);
|
||||
extern int mISDN_free_bch(bchannel_t *);
|
||||
|
||||
static inline void
|
||||
bch_set_para(bchannel_t *bch, mISDN_stPara_t *stp)
|
||||
{
|
||||
if (stp) {
|
||||
bch->maxdatasize = stp->maxdatalen;
|
||||
bch->up_headerlen = stp->up_headerlen;
|
||||
} else {
|
||||
bch->maxdatasize = 0;
|
||||
bch->up_headerlen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
queue_bch_frame(bchannel_t *bch, u_int pr, int dinfo, struct sk_buff *skb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
|
||||
pr |= DL_DATA;
|
||||
else
|
||||
pr |= PH_DATA;
|
||||
err = mISDN_queueup_newhead(&bch->inst, 0, pr, dinfo, skb);
|
||||
if (unlikely(err)) {
|
||||
int_errtxt("err=%d", err);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OBSOLETE
|
||||
static inline void
|
||||
bch_sched_event(bchannel_t *bch, int event)
|
||||
{
|
||||
test_and_set_bit(event, &bch->event);
|
||||
schedule_work(&bch->work);
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,87 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Author (c) Karsten Keil <kkeil@suse.de>
|
||||
*
|
||||
* This file is released under the GPLv2
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include "channel.h"
|
||||
#include "layer1.h"
|
||||
|
||||
int
|
||||
mISDN_initchannel(channel_t *ch, ulong prop, int maxlen)
|
||||
{
|
||||
if (!(ch->log = kmalloc(MAX_LOG_SPACE, GFP_ATOMIC))) {
|
||||
printk(KERN_WARNING
|
||||
"mISDN: No memory for channel log\n");
|
||||
return(-ENOMEM);
|
||||
}
|
||||
ch->Flags = prop;
|
||||
ch->maxlen = maxlen;
|
||||
ch->hw = NULL;
|
||||
ch->rx_skb = NULL;
|
||||
ch->tx_skb = NULL;
|
||||
ch->tx_idx = 0;
|
||||
ch->next_skb = NULL;
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
mISDN_freechannel(channel_t *ch)
|
||||
{
|
||||
if (ch->tx_skb) {
|
||||
dev_kfree_skb(ch->tx_skb);
|
||||
ch->tx_skb = NULL;
|
||||
}
|
||||
if (ch->rx_skb) {
|
||||
dev_kfree_skb(ch->rx_skb);
|
||||
ch->rx_skb = NULL;
|
||||
}
|
||||
if (ch->next_skb) {
|
||||
dev_kfree_skb(ch->next_skb);
|
||||
ch->next_skb = NULL;
|
||||
}
|
||||
kfree(ch->log);
|
||||
ch->log = NULL;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* need called with HW lock */
|
||||
int
|
||||
mISDN_setpara(channel_t *ch, mISDN_stPara_t *stp)
|
||||
{
|
||||
if (!stp) { // clear parameters
|
||||
ch->maxlen = 0;
|
||||
ch->up_headerlen = 0;
|
||||
return(0);
|
||||
}
|
||||
if (stp->up_headerlen)
|
||||
ch->up_headerlen = stp->up_headerlen;
|
||||
if (stp->maxdatalen) {
|
||||
if (ch->maxlen < stp->maxdatalen) {
|
||||
if (ch->rx_skb) {
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = alloc_skb(stp->maxdatalen +
|
||||
ch->up_headerlen, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
int_errtxt("no skb for %d+%d", stp->maxdatalen, ch->up_headerlen);
|
||||
return(-ENOMEM);
|
||||
}
|
||||
skb_reserve(skb, ch->up_headerlen);
|
||||
memcpy(skb_put(skb, ch->rx_skb->len),
|
||||
ch->rx_skb->data, ch->rx_skb->len);
|
||||
dev_kfree_skb(ch->rx_skb);
|
||||
ch->rx_skb = skb;
|
||||
}
|
||||
}
|
||||
ch->maxlen = stp->maxdatalen;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(mISDN_initchannel);
|
||||
EXPORT_SYMBOL(mISDN_freechannel);
|
||||
EXPORT_SYMBOL(mISDN_setpara);
|
|
@ -0,0 +1,148 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Basic declarations for a mISDN HW channel
|
||||
*
|
||||
* Author (c) Karsten Keil <kkeil@suse.de>
|
||||
*
|
||||
* This file is released under the GPLv2
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MISDN_CHANNEL_H
|
||||
#define MISDN_CHANNEL_H
|
||||
#include <linux/mISDNif.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include "helper.h"
|
||||
#ifdef MISDN_MEMDEBUG
|
||||
#include "memdbg.h"
|
||||
#endif
|
||||
|
||||
#define MAX_DFRAME_LEN_L1 300
|
||||
#define MAX_MON_FRAME 32
|
||||
#define MAX_LOG_SPACE 2048
|
||||
#define MISDN_COPY_SIZE 32
|
||||
|
||||
/* channel->Flags bit field */
|
||||
#define FLG_TX_BUSY 0 // tx_buf in use
|
||||
#define FLG_TX_NEXT 1 // next_skb in use
|
||||
#define FLG_L1_BUSY 2 // L1 is permanent busy
|
||||
#define FLG_USED 5 // channel is in use
|
||||
#define FLG_ACTIVE 6 // channel is activated
|
||||
#define FLG_BUSY_TIMER 7
|
||||
/* channel type */
|
||||
#define FLG_DCHANNEL 8 // channel is D-channel
|
||||
#define FLG_BCHANNEL 9 // channel is B-channel
|
||||
#define FLG_ECHANNEL 10 // channel is E-channel
|
||||
#define FLG_TRANSPARENT 12 // channel use transparent data
|
||||
#define FLG_HDLC 13 // channel use hdlc data
|
||||
#define FLG_L2DATA 14 // channel use L2 DATA primitivs
|
||||
#define FLG_ORIGIN 15 // channel is on origin site
|
||||
/* channel specific stuff */
|
||||
/* arcofi specific */
|
||||
#define FLG_ARCOFI_TIMER 16
|
||||
#define FLG_ARCOFI_ERROR 17
|
||||
/* isar specific */
|
||||
#define FLG_INITIALIZED 16
|
||||
#define FLG_DLEETX 17
|
||||
#define FLG_LASTDLE 18
|
||||
#define FLG_FIRST 19
|
||||
#define FLG_LASTDATA 20
|
||||
#define FLG_NMD_DATA 21
|
||||
#define FLG_FTI_RUN 22
|
||||
#define FLG_LL_OK 23
|
||||
#define FLG_LL_CONN 24
|
||||
#define FLG_DTMFSEND 25
|
||||
|
||||
|
||||
#define MSK_INIT_DCHANNEL ((1<<FLG_DCHANNEL)|(1<<FLG_HDLC))
|
||||
#define MSK_INIT_BCHANNEL (1<<FLG_BCHANNEL)
|
||||
#define MSK_INIT_ECHANNEL (1<<FLG_ECHANNEL)
|
||||
|
||||
|
||||
typedef struct _channel_t {
|
||||
mISDNinstance_t inst;
|
||||
int channel;
|
||||
/* basic properties */
|
||||
u_long Flags;
|
||||
u_int type;
|
||||
u_int state;
|
||||
/* HW access */
|
||||
u_char (*read_reg) (void *, u_char);
|
||||
void (*write_reg) (void *, u_char, u_char);
|
||||
void (*read_fifo) (void *, u_char *, int);
|
||||
void (*write_fifo) (void *, u_char *, int);
|
||||
void *hw;
|
||||
struct timer_list timer;
|
||||
/* receive data */
|
||||
struct sk_buff *rx_skb;
|
||||
int maxlen;
|
||||
int up_headerlen;
|
||||
/* send data */
|
||||
struct sk_buff *next_skb;
|
||||
struct sk_buff *tx_skb;
|
||||
int tx_idx;
|
||||
/* debug */
|
||||
int debug;
|
||||
char *log;
|
||||
/* statistics */
|
||||
int err_crc;
|
||||
int err_tx;
|
||||
int err_rx;
|
||||
} channel_t;
|
||||
|
||||
extern int mISDN_initchannel(channel_t *, ulong, int);
|
||||
extern int mISDN_freechannel(channel_t *);
|
||||
extern int mISDN_setpara(channel_t *, mISDN_stPara_t *);
|
||||
|
||||
static inline void
|
||||
queue_ch_frame(channel_t *ch, u_int pr, int dinfo, struct sk_buff *skb)
|
||||
{
|
||||
int err;
|
||||
|
||||
pr |= test_bit(FLG_L2DATA, &ch->Flags) ? DL_DATA : PH_DATA;
|
||||
if (!skb)
|
||||
err = mISDN_queue_data(&ch->inst, FLG_MSG_UP, pr, dinfo, 0, NULL, ch->up_headerlen);
|
||||
else
|
||||
err = mISDN_queueup_newhead(&ch->inst, 0, pr, dinfo, skb);
|
||||
if (unlikely(err)) {
|
||||
int_errtxt("err=%d", err);
|
||||
if (skb)
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
channel_senddata(channel_t *ch, int di, struct sk_buff *skb)
|
||||
{
|
||||
/* HW lock must be obtained */
|
||||
/* check oversize */
|
||||
if (skb->len <= 0) {
|
||||
printk(KERN_WARNING "%s: skb too small\n", __FUNCTION__);
|
||||
return(-EINVAL);
|
||||
}
|
||||
if (skb->len > ch->maxlen) {
|
||||
printk(KERN_WARNING "%s: skb too large(%d/%d)\n",
|
||||
__FUNCTION__, skb->len, ch->maxlen);
|
||||
return(-EINVAL);
|
||||
}
|
||||
/* check for pending next_skb */
|
||||
if (ch->next_skb) {
|
||||
printk(KERN_WARNING "%s: next_skb exist ERROR (skb->len=%d next_skb->len=%d)\n",
|
||||
__FUNCTION__, skb->len, ch->next_skb->len);
|
||||
return(-EBUSY);
|
||||
}
|
||||
if (test_and_set_bit(FLG_TX_BUSY, &ch->Flags)) {
|
||||
test_and_set_bit(FLG_TX_NEXT, &ch->Flags);
|
||||
ch->next_skb = skb;
|
||||
return(0);
|
||||
} else {
|
||||
/* write to fifo */
|
||||
ch->tx_skb = skb;
|
||||
ch->tx_idx = 0;
|
||||
queue_ch_frame(ch, CONFIRM, di, NULL);
|
||||
return(skb->len);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,118 +0,0 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Author Karsten Keil (keil@isdn4linux.de)
|
||||
*
|
||||
* This file is (c) under GNU PUBLIC LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mISDNif.h>
|
||||
#include "layer1.h"
|
||||
#include "helper.h"
|
||||
#include "dchannel.h"
|
||||
|
||||
#ifdef OBSOLETE
|
||||
static void
|
||||
dchannel_bh(dchannel_t *dch)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
mISDN_head_t *hh;
|
||||
|
||||
if (!dch)
|
||||
return;
|
||||
if (dch->debug)
|
||||
printk(KERN_DEBUG "%s: event %lx\n", __FUNCTION__, dch->event);
|
||||
#if 0
|
||||
if (test_and_clear_bit(D_CLEARBUSY, &dch->event)) {
|
||||
if (dch->debug)
|
||||
mISDN_debugprint(&dch->inst, "D-Channel Busy cleared");
|
||||
stptr = dch->stlist;
|
||||
while (stptr != NULL) {
|
||||
stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
|
||||
stptr = stptr->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (test_and_clear_bit(D_XMTBUFREADY, &dch->event)) {
|
||||
if ((skb = dch->next_skb)) {
|
||||
hh = mISDN_HEAD_P(skb);
|
||||
dch->next_skb = NULL;
|
||||
skb_trim(skb, 0);
|
||||
if (mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_CNF, hh->dinfo, skb))
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(D_RCVBUFREADY, &dch->event)) {
|
||||
while ((skb = skb_dequeue(&dch->rqueue))) {
|
||||
err = mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_IND, MISDN_ID_ANY, skb);
|
||||
if (err < 0) {
|
||||
printk(KERN_WARNING "%s: deliver err %d\n", __FUNCTION__, err);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dch->hw_bh)
|
||||
dch->hw_bh(dch);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
mISDN_init_dch(dchannel_t *dch) {
|
||||
if (!(dch->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
|
||||
printk(KERN_WARNING
|
||||
"mISDN: No memory for dlog\n");
|
||||
return(-ENOMEM);
|
||||
}
|
||||
if (!(dch->tx_buf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
|
||||
printk(KERN_WARNING
|
||||
"mISDN: No memory for dchannel tx_buf\n");
|
||||
kfree(dch->dlog);
|
||||
dch->dlog = NULL;
|
||||
return(-ENOMEM);
|
||||
}
|
||||
dch->hw = NULL;
|
||||
dch->rx_skb = NULL;
|
||||
dch->tx_idx = 0;
|
||||
dch->next_skb = NULL;
|
||||
#ifdef OBSOLETE
|
||||
dch->event = 0;
|
||||
INIT_WORK(&dch->work, (void *)(void *)dchannel_bh, dch);
|
||||
dch->hw_bh = NULL;
|
||||
skb_queue_head_init(&dch->rqueue);
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
mISDN_free_dch(dchannel_t *dch) {
|
||||
#ifdef OBSOLETE
|
||||
#ifdef HAS_WORKQUEUE
|
||||
if (dch->work.pending)
|
||||
printk(KERN_ERR "mISDN_free_dch work:(%lx)\n", dch->work.pending);
|
||||
#else
|
||||
if (dch->work.sync)
|
||||
printk(KERN_ERR "mISDN_free_dch work:(%lx)\n", dch->work.sync);
|
||||
#endif
|
||||
discard_queue(&dch->rqueue);
|
||||
#endif
|
||||
if (dch->rx_skb) {
|
||||
dev_kfree_skb(dch->rx_skb);
|
||||
dch->rx_skb = NULL;
|
||||
}
|
||||
kfree(dch->tx_buf);
|
||||
dch->tx_buf = NULL;
|
||||
if (dch->next_skb) {
|
||||
dev_kfree_skb(dch->next_skb);
|
||||
dch->next_skb = NULL;
|
||||
}
|
||||
kfree(dch->dlog);
|
||||
dch->dlog = NULL;
|
||||
return(0);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(mISDN_init_dch);
|
||||
EXPORT_SYMBOL(mISDN_free_dch);
|
|
@ -1,96 +0,0 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Basic declarations for dchannel HW
|
||||
*
|
||||
* This file is (c) under GNU PUBLIC LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/mISDNif.h>
|
||||
#ifdef HAS_WORKQUEUE
|
||||
#include <linux/workqueue.h>
|
||||
#else
|
||||
#include <linux/tqueue.h>
|
||||
#endif
|
||||
#include <linux/smp.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/timer.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/skbuff.h>
|
||||
#ifdef MISDN_MEMDEBUG
|
||||
#include "memdbg.h"
|
||||
#endif
|
||||
|
||||
#define MAX_DFRAME_LEN_L1 300
|
||||
#define MAX_MON_FRAME 32
|
||||
#define MAX_DLOG_SPACE 2048
|
||||
|
||||
#define FLG_TWO_DCHAN 4
|
||||
#define FLG_TX_BUSY 5
|
||||
#define FLG_TX_NEXT 6
|
||||
#define FLG_L1_DBUSY 7
|
||||
#define FLG_DBUSY_TIMER 8
|
||||
#define FLG_LOCK_ATOMIC 9
|
||||
#define FLG_ARCOFI_TIMER 10
|
||||
#define FLG_ARCOFI_ERROR 11
|
||||
#define FLG_HW_L1_UINT 12
|
||||
#define FLG_HW_INIT 13
|
||||
|
||||
typedef struct _dchannel_t {
|
||||
int channel;
|
||||
mISDNinstance_t inst;
|
||||
u_long DFlags;
|
||||
u_int type;
|
||||
u_int ph_state;
|
||||
u_char l1_up;
|
||||
u_char (*read_reg) (void *, u_char);
|
||||
void (*write_reg) (void *, u_char, u_char);
|
||||
void (*read_fifo) (void *, u_char *, int);
|
||||
void (*write_fifo) (void *, u_char *, int);
|
||||
char *dlog;
|
||||
int debug;
|
||||
struct sk_buff *rx_skb;
|
||||
struct sk_buff *next_skb;
|
||||
u_char *tx_buf;
|
||||
int tx_idx;
|
||||
int tx_len;
|
||||
int up_headerlen;
|
||||
int err_crc;
|
||||
int err_tx;
|
||||
int err_rx;
|
||||
void *hw;
|
||||
struct timer_list dbusytimer;
|
||||
#ifdef OBSOLETE
|
||||
u_long event;
|
||||
struct sk_buff_head rqueue; /* D-channel receive queue */
|
||||
struct work_struct work;
|
||||
#endif
|
||||
void (*hw_bh) (struct _dchannel_t *);
|
||||
} dchannel_t;
|
||||
|
||||
#define MON0_RX 1
|
||||
#define MON1_RX 2
|
||||
#define MON0_TX 4
|
||||
#define MON1_TX 8
|
||||
|
||||
extern int mISDN_init_dch(dchannel_t *);
|
||||
extern int mISDN_free_dch(dchannel_t *);
|
||||
|
||||
static inline void
|
||||
dch_set_para(dchannel_t *dch, mISDN_stPara_t *stp)
|
||||
{
|
||||
if (stp)
|
||||
dch->up_headerlen = stp->up_headerlen;
|
||||
else
|
||||
dch->up_headerlen = 0;
|
||||
}
|
||||
#ifdef OBSOLETE
|
||||
static inline void
|
||||
dchannel_sched_event(dchannel_t *dch, int event)
|
||||
{
|
||||
test_and_set_bit(event, &dch->event);
|
||||
schedule_work(&dch->work);
|
||||
}
|
||||
#endif
|
|
@ -176,14 +176,6 @@ mISDN_sethead(u_int prim, int dinfo, struct sk_buff *skb)
|
|||
hh->dinfo = dinfo;
|
||||
}
|
||||
|
||||
static inline int mISDN_send_message(void) {return 0;};
|
||||
static inline int mISDN_send_data(void) {return 0;};
|
||||
static inline int mISDN_sendup(void) {return 0;};
|
||||
static inline int mISDN_sendup_newhead(void) {return 0;};
|
||||
static inline int mISDN_senddown(void) {return 0;};
|
||||
static inline int mISDN_senddown_newhead(void) {return 0;};
|
||||
|
||||
|
||||
#define mISDN_queue_up(i, a, s) mISDN_queue_message(i, a | FLG_MSG_UP, s)
|
||||
#define mISDN_queue_down(i, a, s) mISDN_queue_message(i, a | FLG_MSG_DOWN, s)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -35,27 +35,22 @@ typedef unsigned long DWORD;
|
|||
also registers are assigned differen for HFC-4s/8s and HFC-E1
|
||||
*/
|
||||
|
||||
#define MAX_FRAME_SIZE 2048
|
||||
// #define MAX_FRAME_SIZE 2048
|
||||
|
||||
struct hfc_chan {
|
||||
/* dch or bch is set, otherwhise this channel is not used */
|
||||
dchannel_t *dch; /* link if channel is a D-channel */
|
||||
bchannel_t *bch; /* link if channel is a B-channel */
|
||||
int rx_idx; /* for D-channel */
|
||||
BYTE *rx_buf; /* for D-channel */
|
||||
int port; /* the interface port this channel is associated with */
|
||||
int nt_mode;
|
||||
channel_t *ch; /* link if channel is a D-channel */
|
||||
int port; /* the interface port this channel is associated with */
|
||||
int nt_timer; /* -1 if off, 0 if elapsed, >0 if running */
|
||||
int los, ais, slip_tx, slip_rx; /* current alarms */
|
||||
int jitter;
|
||||
u_long cfg; /* port configuration */
|
||||
int sync; /* sync state (used by E1) */
|
||||
DWORD protocol; /* current protocol */
|
||||
u_long cfg; /* port configuration */
|
||||
int sync; /* sync state (used by E1) */
|
||||
DWORD protocol;/* current protocol */
|
||||
int slot_tx; /* current pcm slot */
|
||||
int bank_tx; /* current pcm bank */
|
||||
int slot_rx;
|
||||
int bank_rx;
|
||||
int conf; /* conference setting of TX slot */
|
||||
int conf; /* conference setting of TX slot */
|
||||
int txpending; /* if there is currently data in the FIFO 0=no, 1=yes, 2=splloop */
|
||||
int e1_state; /* keep track of last state */
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -24,8 +24,7 @@
|
|||
#ifndef __HFCMINI_H__
|
||||
#define __HFCMINI_H__
|
||||
|
||||
#include "dchannel.h"
|
||||
#include "bchannel.h"
|
||||
#include "channel.h"
|
||||
#include "hfcsmcc.h"
|
||||
|
||||
|
||||
|
@ -105,17 +104,6 @@ typedef struct {
|
|||
char *device_name;
|
||||
} hfcsmini_param;
|
||||
|
||||
|
||||
/* channel struct for each fifo */
|
||||
typedef struct {
|
||||
bchannel_t *bch;
|
||||
dchannel_t *dch;
|
||||
int rx_idx; /* for D-channel */
|
||||
__u8 *rx_buf; /* for D-channel */
|
||||
} hfcmini_chan_t;
|
||||
|
||||
|
||||
|
||||
struct _hfcmini_hw;
|
||||
|
||||
/**********************/
|
||||
|
@ -143,7 +131,7 @@ typedef struct _hfcmini_hw {
|
|||
int max_fifo; /* always 4 fifos per port */
|
||||
__u8 max_z; /* fifo depth -1 */
|
||||
|
||||
hfcmini_chan_t chan[MAX_CHAN]; /* line interfaces */
|
||||
channel_t chan[MAX_CHAN]; /* line interfaces */
|
||||
|
||||
__u8 fifomask;
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/usb.h>
|
||||
#include "dchannel.h"
|
||||
#include "channel.h"
|
||||
#include "bchannel.h"
|
||||
#include "layer1.h"
|
||||
#include "debug.h"
|
||||
|
@ -105,7 +105,7 @@ typedef struct usb_fifo {
|
|||
typedef struct _hfcsusb_t {
|
||||
struct list_head list;
|
||||
spinlock_t lock;
|
||||
dchannel_t dch;
|
||||
channel_t dch;
|
||||
bchannel_t bch[2];
|
||||
|
||||
struct usb_device *dev; /* our device */
|
||||
|
@ -404,7 +404,7 @@ hfcsusb_manager(void *data, u_int prim, void *arg)
|
|||
switch (prim) {
|
||||
case MGR_REGLAYER | CONFIRM:
|
||||
if (channel == 2)
|
||||
dch_set_para(&card->dch, &inst->st->para);
|
||||
mISDN_setpara(&card->dch, &inst->st->para);
|
||||
else
|
||||
bch_set_para(&card->bch[channel],
|
||||
&inst->st->para);
|
||||
|
@ -427,7 +427,7 @@ hfcsusb_manager(void *data, u_int prim, void *arg)
|
|||
arg = NULL;
|
||||
case MGR_ADDSTPARA | INDICATION:
|
||||
if (channel == 2)
|
||||
dch_set_para(&card->dch, arg);
|
||||
mISDN_setpara(&card->dch, arg);
|
||||
else
|
||||
bch_set_para(&card->bch[channel], arg);
|
||||
break;
|
||||
|
@ -480,7 +480,7 @@ hfcsusb_manager(void *data, u_int prim, void *arg)
|
|||
/* S0 state change event handler */
|
||||
/*********************************/
|
||||
static void
|
||||
S0_new_state(dchannel_t * dch)
|
||||
S0_new_state(channel_t * dch)
|
||||
{
|
||||
u_int prim = PH_SIGNAL | INDICATION;
|
||||
u_int para = 0;
|
||||
|
@ -490,9 +490,9 @@ S0_new_state(dchannel_t * dch)
|
|||
if (dch->debug)
|
||||
mISDN_debugprint(&card->dch.inst,
|
||||
"%s: TE %d",
|
||||
__FUNCTION__, dch->ph_state);
|
||||
__FUNCTION__, dch->state);
|
||||
|
||||
switch (dch->ph_state) {
|
||||
switch (dch->state) {
|
||||
case (0):
|
||||
prim = PH_CONTROL | INDICATION;
|
||||
para = HW_RESET;
|
||||
|
@ -520,9 +520,9 @@ S0_new_state(dchannel_t * dch)
|
|||
if (dch->debug)
|
||||
mISDN_debugprint(&card->dch.inst,
|
||||
"%s: NT %d",
|
||||
__FUNCTION__, dch->ph_state);
|
||||
__FUNCTION__, dch->state);
|
||||
|
||||
switch (dch->ph_state) {
|
||||
switch (dch->state) {
|
||||
case (1):
|
||||
dch->l1_up = 0;
|
||||
card->nt_timer = 0;
|
||||
|
@ -573,11 +573,11 @@ S0_new_state(dchannel_t * dch)
|
|||
static void
|
||||
state_handler(hfcsusb_t * card, __u8 new_l1_state)
|
||||
{
|
||||
if (new_l1_state == card->dch.ph_state
|
||||
if (new_l1_state == card->dch.state
|
||||
|| new_l1_state < 1 || new_l1_state > 8)
|
||||
return;
|
||||
|
||||
card->dch.ph_state = new_l1_state;
|
||||
card->dch.state = new_l1_state;
|
||||
S0_new_state(&card->dch);
|
||||
}
|
||||
|
||||
|
@ -720,19 +720,19 @@ hfcsusb_ph_command(hfcsusb_t * card, u_char command)
|
|||
case S0_L1CMD_AR8:
|
||||
mISDN_debugprint(&card->dch.inst,
|
||||
"S0_L1CMD_AR8 at ph_sate = %i",
|
||||
&card->dch.ph_state);
|
||||
&card->dch.state);
|
||||
break;
|
||||
|
||||
case S0_L1CMD_AR10:
|
||||
mISDN_debugprint(&card->dch.inst,
|
||||
"S0_L1CMD_AR10 at ph_sate = %i",
|
||||
&card->dch.ph_state);
|
||||
&card->dch.state);
|
||||
break;
|
||||
|
||||
case S0_L1CMD_ECK:
|
||||
mISDN_debugprint(&card->dch.inst,
|
||||
"S0_L1CMD_ECK at ph_sate = %i",
|
||||
&card->dch.ph_state);
|
||||
&card->dch.state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -743,7 +743,7 @@ hfcsusb_ph_command(hfcsusb_t * card, u_char command)
|
|||
static int
|
||||
hfcsusb_l1hwD(mISDNinstance_t *inst, struct sk_buff *skb)
|
||||
{
|
||||
dchannel_t *dch = container_of(inst, dchannel_t, inst);
|
||||
channel_t *dch = container_of(inst, channel_t, inst);
|
||||
int ret = 0;
|
||||
mISDN_head_t *hh = mISDN_HEAD_P(skb);
|
||||
hfcsusb_t *card = inst->privat;
|
||||
|
@ -767,22 +767,18 @@ hfcsusb_l1hwD(mISDNinstance_t *inst, struct sk_buff *skb)
|
|||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
return (-EBUSY);
|
||||
}
|
||||
if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) {
|
||||
test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
|
||||
if (test_and_set_bit(FLG_TX_BUSY, &dch->Flags)) {
|
||||
test_and_set_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
dch->next_skb = skb;
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
return (0);
|
||||
} else {
|
||||
/* prepare buffer, which is transmitted by
|
||||
tx_iso completions later */
|
||||
dch->tx_len = skb->len;
|
||||
memcpy(dch->tx_buf, skb->data, dch->tx_len);
|
||||
dch->tx_skb = skb;
|
||||
dch->tx_idx = 0;
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
skb_trim(skb, 0);
|
||||
return(mISDN_queueup_newhead(inst, 0, PH_DATA_CNF,
|
||||
hh->dinfo, skb));
|
||||
queue_ch_frame(dch, CONFIRM, hh->dinfo, NULL);
|
||||
}
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
return (0);
|
||||
} else if (hh->prim == (PH_SIGNAL | REQUEST)) {
|
||||
spin_lock_irqsave(inst->hwlock, flags);
|
||||
if (hh->dinfo == INFO3_P8)
|
||||
|
@ -796,7 +792,7 @@ hfcsusb_l1hwD(mISDNinstance_t *inst, struct sk_buff *skb)
|
|||
} else if (hh->prim == (PH_CONTROL | REQUEST)) {
|
||||
spin_lock_irqsave(inst->hwlock, flags);
|
||||
if (hh->dinfo == HW_RESET) {
|
||||
if (dch->ph_state != 0)
|
||||
if (dch->state != 0)
|
||||
hfcsusb_ph_command(dch->hw,
|
||||
HFC_L1_ACTIVATE_TE);
|
||||
hfcsusb_ph_command(dch->hw, S0_L1CMD_ECK);
|
||||
|
@ -807,10 +803,10 @@ hfcsusb_l1hwD(mISDNinstance_t *inst, struct sk_buff *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);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
|
||||
#ifdef FIXME
|
||||
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
|
||||
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->Flags))
|
||||
dchannel_sched_event(dch, D_CLEARBUSY);
|
||||
#endif
|
||||
} else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) {
|
||||
|
@ -1285,27 +1281,28 @@ rx_int_complete(struct urb *urb, struct pt_regs *regs)
|
|||
void
|
||||
next_d_tx_frame(hfcsusb_t * card)
|
||||
{
|
||||
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);
|
||||
|
||||
if(card->dch.tx_skb)
|
||||
dev_kfree_skb(card->dch.tx_skb);
|
||||
if (test_bit(FLG_TX_NEXT, &card->dch.Flags)) {
|
||||
card->dch.tx_skb = card->dch.next_skb;
|
||||
if (card->dch.tx_skb) {
|
||||
mISDN_head_t *hh = mISDN_HEAD_P(card->dch.tx_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);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &card->dch.Flags);
|
||||
card->dch.tx_idx = 0;
|
||||
skb_trim(skb, 0);
|
||||
if (mISDN_queueup_newhead(&card->dch.inst, 0, PH_DATA_CNF, hh->dinfo, skb))
|
||||
dev_kfree_skb(skb);
|
||||
queue_ch_frame(&card->dch, CONFIRM, hh->dinfo, NULL);
|
||||
} else {
|
||||
printk(KERN_WARNING
|
||||
"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_NEXT, &card->dch.Flags);
|
||||
test_and_clear_bit(FLG_TX_BUSY, &card->dch.Flags);
|
||||
}
|
||||
} else
|
||||
test_and_clear_bit(FLG_TX_BUSY, &card->dch.DFlags);
|
||||
} else {
|
||||
card->dch.tx_skb = NULL;
|
||||
test_and_clear_bit(FLG_TX_BUSY, &card->dch.Flags);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1342,7 +1339,7 @@ tx_iso_complete(struct urb *urb, struct pt_regs *regs)
|
|||
hfcsusb_t *card = fifo->card;
|
||||
int k, tx_offset, num_isoc_packets, sink, len, current_len,
|
||||
errcode;
|
||||
int *tx_len, *tx_idx;
|
||||
int tx_len, *tx_idx;
|
||||
u_char *tx_buf;
|
||||
int frame_complete, transp_mode=0, fifon, status;
|
||||
__u8 threshbit;
|
||||
|
@ -1374,14 +1371,19 @@ tx_iso_complete(struct urb *urb, struct pt_regs *regs)
|
|||
|
||||
switch (fifon) {
|
||||
case HFCUSB_D_TX:
|
||||
tx_buf = card->dch.tx_buf;
|
||||
tx_len = &card->dch.tx_len;
|
||||
if (!card->dch.tx_skb) {
|
||||
tx_buf = NULL;
|
||||
tx_len = 0;
|
||||
} else {
|
||||
tx_buf = card->dch.tx_skb->data;
|
||||
tx_len = card->dch.tx_skb->len;
|
||||
}
|
||||
tx_idx = &card->dch.tx_idx;
|
||||
break;
|
||||
case HFCUSB_B1_TX:
|
||||
case HFCUSB_B2_TX:
|
||||
tx_buf = card->bch[fifo->bch_idx].tx_buf;
|
||||
tx_len = &card->bch[fifo->bch_idx].tx_len;
|
||||
tx_len = card->bch[fifo->bch_idx].tx_len;
|
||||
tx_idx = &card->bch[fifo->bch_idx].tx_idx;
|
||||
transp_mode = card->bch[fifo->bch_idx].protocol == ISDN_PID_L1_B_64TRANS;
|
||||
break;
|
||||
|
@ -1394,17 +1396,15 @@ tx_iso_complete(struct urb *urb, struct pt_regs *regs)
|
|||
|
||||
/* Generate next Iso Packets */
|
||||
for (k = 0; k < num_isoc_packets; ++k) {
|
||||
len = (*tx_len - *tx_idx);
|
||||
if (len) {
|
||||
len = (tx_len - *tx_idx);
|
||||
if (len>0) {
|
||||
/* we lower data margin every msec */
|
||||
fifo->bit_line -= sink;
|
||||
current_len = (0 - fifo->bit_line) / 8;
|
||||
/* maximum 15 byte for every ISO packet makes our life easier */
|
||||
if (current_len > 14)
|
||||
current_len = 14;
|
||||
current_len =
|
||||
(len <=
|
||||
current_len) ? len : current_len;
|
||||
current_len = (len <= current_len) ? len : current_len;
|
||||
|
||||
/* how much bit do we put on the line? */
|
||||
fifo->bit_line += current_len * 8;
|
||||
|
@ -1413,8 +1413,7 @@ tx_iso_complete(struct urb *urb, struct pt_regs *regs)
|
|||
if (current_len == len) {
|
||||
if (!transp_mode) {
|
||||
/* here frame completion */
|
||||
context_iso_urb->
|
||||
buffer[tx_offset] = 1;
|
||||
context_iso_urb->buffer[tx_offset] = 1;
|
||||
/* add 2 byte flags and 16bit CRC at end of ISDN frame */
|
||||
fifo->bit_line += 32;
|
||||
}
|
||||
|
@ -1422,20 +1421,18 @@ tx_iso_complete(struct urb *urb, struct pt_regs *regs)
|
|||
}
|
||||
|
||||
/* copy tx data to iso-urb buffer */
|
||||
memcpy(context_iso_urb->buffer +
|
||||
tx_offset + 1,
|
||||
memcpy(context_iso_urb->buffer + tx_offset + 1,
|
||||
(tx_buf + *tx_idx), current_len);
|
||||
*tx_idx += current_len;
|
||||
|
||||
/* define packet delimeters within the URB buffer */
|
||||
urb->iso_frame_desc[k].offset = tx_offset;
|
||||
urb->iso_frame_desc[k].length =
|
||||
current_len + 1;
|
||||
current_len + 1;
|
||||
|
||||
tx_offset += (current_len + 1);
|
||||
} else {
|
||||
urb->iso_frame_desc[k].offset =
|
||||
tx_offset++;
|
||||
urb->iso_frame_desc[k].offset = tx_offset++;
|
||||
|
||||
urb->iso_frame_desc[k].length = 1;
|
||||
fifo->bit_line -= sink; /* we lower data margin every msec */
|
||||
|
@ -1452,14 +1449,17 @@ tx_iso_complete(struct urb *urb, struct pt_regs *regs)
|
|||
switch (fifon) {
|
||||
case HFCUSB_D_TX:
|
||||
next_d_tx_frame(card);
|
||||
if (fifo->skbuff
|
||||
&& fifo->delete_flg) {
|
||||
dev_kfree_skb_any
|
||||
(fifo->skbuff);
|
||||
fifo->skbuff =
|
||||
NULL;
|
||||
fifo->delete_flg =
|
||||
0;
|
||||
if (card->dch.tx_skb) {
|
||||
tx_len = card->dch.tx_skb->len;
|
||||
tx_buf = card->dch.tx_skb->data;
|
||||
} else {
|
||||
tx_len = 0;
|
||||
tx_buf = NULL;
|
||||
}
|
||||
if (fifo->skbuff && fifo->delete_flg) {
|
||||
dev_kfree_skb_any(fifo->skbuff);
|
||||
fifo->skbuff = NULL;
|
||||
fifo->delete_flg = 0;
|
||||
}
|
||||
frame_complete = 0;
|
||||
break;
|
||||
|
@ -1468,15 +1468,12 @@ tx_iso_complete(struct urb *urb, struct pt_regs *regs)
|
|||
case HFCUSB_B2_TX:
|
||||
next_b_tx_frame(card, fifo->bch_idx);
|
||||
|
||||
card->bch[fifo->bch_idx].tx_len =
|
||||
0;
|
||||
test_and_clear_bit
|
||||
(BC_FLG_TX_BUSY,
|
||||
&card->bch[fifo->bch_idx].
|
||||
Flag);
|
||||
card->bch[fifo->bch_idx].tx_len = 0;
|
||||
tx_len = 0;
|
||||
test_and_clear_bit(BC_FLG_TX_BUSY,
|
||||
&card->bch[fifo->bch_idx].Flag);
|
||||
card->bch[fifo->bch_idx].tx_idx =
|
||||
card->bch[fifo->bch_idx].
|
||||
tx_len;
|
||||
card->bch[fifo->bch_idx].tx_len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1633,13 +1630,10 @@ start_int_fifo(usb_fifo * fifo)
|
|||
void
|
||||
hw_init(hfcsusb_t * card)
|
||||
{
|
||||
/* setup basic function pointers */
|
||||
card->dch.hw_bh = S0_new_state;
|
||||
|
||||
/* init bchannel mode */
|
||||
mode_bchannel(&card->bch[0], 0, -1);
|
||||
mode_bchannel(&card->bch[1], 1, -1);
|
||||
card->dch.ph_state = 0;
|
||||
card->dch.state = 0;
|
||||
}
|
||||
|
||||
/* Hardware Initialization */
|
||||
|
@ -1797,7 +1791,7 @@ release_card(hfcsusb_t * card)
|
|||
mode_bchannel(&card->bch[1], 1, ISDN_PID_NONE);
|
||||
mISDN_free_bch(&card->bch[1]);
|
||||
mISDN_free_bch(&card->bch[0]);
|
||||
mISDN_free_dch(&card->dch);
|
||||
mISDN_freechannel(&card->dch);
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
hw_mISDNObj.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
spin_lock_irqsave(&hw_mISDNObj.lock, flags);
|
||||
|
@ -1856,7 +1850,7 @@ setup_instance(hfcsusb_t * 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]);
|
||||
mISDN_init_dch(&card->dch);
|
||||
mISDN_initchannel(&card->dch, MSK_DCHANNEL, MAX_DFRAME_LEN_L1);
|
||||
card->dch.hw = card;
|
||||
card->hw_mode = 0;
|
||||
|
||||
|
@ -1906,7 +1900,7 @@ setup_instance(hfcsusb_t * card)
|
|||
|
||||
err = setup_hfcsusb(card);
|
||||
if (err) {
|
||||
mISDN_free_dch(&card->dch);
|
||||
mISDN_freechannel(&card->dch);
|
||||
mISDN_free_bch(&card->bch[1]);
|
||||
mISDN_free_bch(&card->bch[0]);
|
||||
spin_lock_irqsave(&hw_mISDNObj.lock, flags);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include "dchannel.h"
|
||||
#include "channel.h"
|
||||
#include "isac.h"
|
||||
#include "arcofi.h"
|
||||
#include "layer1.h"
|
||||
|
@ -19,8 +19,8 @@
|
|||
#endif
|
||||
|
||||
|
||||
#define DBUSY_TIMER_VALUE 80
|
||||
#define ARCOFI_USE 1
|
||||
#define DBUSY_TIMER_VALUE 80
|
||||
#define ARCOFI_USE 1
|
||||
|
||||
const char *isac_revision = "$Revision$";
|
||||
|
||||
|
@ -37,7 +37,7 @@ EXPORT_SYMBOL(mISDN_ISAC_l1hw);
|
|||
#endif
|
||||
|
||||
static inline void
|
||||
ph_command(dchannel_t *dch, unsigned int command)
|
||||
ph_command(channel_t *dch, unsigned int command)
|
||||
{
|
||||
if (dch->debug & L1_DEB_ISAC)
|
||||
mISDN_debugprint(&dch->inst, "ph_command %x", command);
|
||||
|
@ -48,12 +48,12 @@ ph_command(dchannel_t *dch, unsigned int command)
|
|||
}
|
||||
|
||||
static void
|
||||
isac_ph_state_change(dchannel_t *dch)
|
||||
isac_ph_state_change(channel_t *dch)
|
||||
{
|
||||
u_int prim = PH_SIGNAL | INDICATION;
|
||||
u_int para = 0;
|
||||
|
||||
switch (dch->ph_state) {
|
||||
switch (dch->state) {
|
||||
case (ISAC_IND_RS):
|
||||
case (ISAC_IND_EI):
|
||||
ph_command(dch, ISAC_CMD_DUI);
|
||||
|
@ -92,7 +92,7 @@ isac_ph_state_change(dchannel_t *dch)
|
|||
|
||||
#ifdef OBSOLETE
|
||||
static void
|
||||
isac_hwbh(dchannel_t *dch)
|
||||
isac_hwbh(channel_t *dch)
|
||||
{
|
||||
if (dch->debug)
|
||||
printk(KERN_DEBUG "%s: event %lx\n", __FUNCTION__, dch->event);
|
||||
|
@ -110,7 +110,7 @@ isac_hwbh(dchannel_t *dch)
|
|||
#endif
|
||||
|
||||
void
|
||||
isac_empty_fifo(dchannel_t *dch, int count)
|
||||
isac_empty_fifo(channel_t *dch, int count)
|
||||
{
|
||||
u_char *ptr;
|
||||
|
||||
|
@ -135,24 +135,25 @@ isac_empty_fifo(dchannel_t *dch, int count)
|
|||
dch->read_fifo(dch->inst.privat, ptr, count);
|
||||
dch->write_reg(dch->inst.privat, ISAC_CMDR, 0x80);
|
||||
if (dch->debug & L1_DEB_ISAC_FIFO) {
|
||||
char *t = dch->dlog;
|
||||
char *t = dch->log;
|
||||
|
||||
t += sprintf(t, "isac_empty_fifo cnt %d", count);
|
||||
mISDN_QuickHex(t, ptr, count);
|
||||
mISDN_debugprint(&dch->inst, dch->dlog);
|
||||
mISDN_debugprint(&dch->inst, dch->log);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
isac_fill_fifo(dchannel_t *dch)
|
||||
isac_fill_fifo(channel_t *dch)
|
||||
{
|
||||
int count, more;
|
||||
u_char *ptr;
|
||||
|
||||
if ((dch->debug & L1_DEB_ISAC) && !(dch->debug & L1_DEB_ISAC_FIFO))
|
||||
mISDN_debugprint(&dch->inst, "isac_fill_fifo");
|
||||
|
||||
count = dch->tx_len - dch->tx_idx;
|
||||
if (!dch->tx_skb)
|
||||
return;
|
||||
count = dch->tx_skb->len - dch->tx_idx;
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
|
@ -161,28 +162,28 @@ isac_fill_fifo(dchannel_t *dch)
|
|||
more = !0;
|
||||
count = 32;
|
||||
}
|
||||
ptr = dch->tx_buf + dch->tx_idx;
|
||||
ptr = dch->tx_skb->data + dch->tx_idx;
|
||||
dch->tx_idx += count;
|
||||
dch->write_fifo(dch->inst.privat, ptr, count);
|
||||
dch->write_reg(dch->inst.privat, ISAC_CMDR, more ? 0x8 : 0xa);
|
||||
if (test_and_set_bit(FLG_DBUSY_TIMER, &dch->DFlags)) {
|
||||
if (test_and_set_bit(FLG_BUSY_TIMER, &dch->Flags)) {
|
||||
mISDN_debugprint(&dch->inst, "isac_fill_fifo dbusytimer running");
|
||||
del_timer(&dch->dbusytimer);
|
||||
del_timer(&dch->timer);
|
||||
}
|
||||
init_timer(&dch->dbusytimer);
|
||||
dch->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
|
||||
add_timer(&dch->dbusytimer);
|
||||
init_timer(&dch->timer);
|
||||
dch->timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
|
||||
add_timer(&dch->timer);
|
||||
if (dch->debug & L1_DEB_ISAC_FIFO) {
|
||||
char *t = dch->dlog;
|
||||
char *t = dch->log;
|
||||
|
||||
t += sprintf(t, "isac_fill_fifo cnt %d", count);
|
||||
mISDN_QuickHex(t, ptr, count);
|
||||
mISDN_debugprint(&dch->inst, dch->dlog);
|
||||
mISDN_debugprint(&dch->inst, dch->log);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
isac_rme_irq(dchannel_t *dch)
|
||||
isac_rme_irq(channel_t *dch)
|
||||
{
|
||||
u_char val;
|
||||
u_int count;
|
||||
|
@ -221,76 +222,74 @@ isac_rme_irq(dchannel_t *dch)
|
|||
}
|
||||
|
||||
static void
|
||||
isac_xpr_irq(dchannel_t *dch)
|
||||
isac_xpr_irq(channel_t *dch)
|
||||
{
|
||||
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
|
||||
del_timer(&dch->dbusytimer);
|
||||
if (dch->tx_idx < dch->tx_len) {
|
||||
if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
|
||||
del_timer(&dch->timer);
|
||||
if (dch->tx_skb && dch->tx_idx < dch->tx_skb->len) {
|
||||
isac_fill_fifo(dch);
|
||||
} else {
|
||||
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) {
|
||||
if (dch->tx_skb)
|
||||
dev_kfree_skb(dch->tx_skb);
|
||||
if (test_bit(FLG_TX_NEXT, &dch->Flags)) {
|
||||
dch->tx_skb = dch->next_skb;
|
||||
if (dch->tx_skb) {
|
||||
mISDN_head_t *hh = mISDN_HEAD_P(dch->tx_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);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
dch->tx_idx = 0;
|
||||
queue_ch_frame(dch, CONFIRM, hh->dinfo, NULL);
|
||||
isac_fill_fifo(dch);
|
||||
skb_trim(skb, 0);
|
||||
if (unlikely(mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_CNF, hh->dinfo, skb))) {
|
||||
int_error();
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
} 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);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
|
||||
}
|
||||
} else
|
||||
test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
|
||||
} else {
|
||||
dch->tx_skb = NULL;
|
||||
test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
isac_retransmit(dchannel_t *dch)
|
||||
isac_retransmit(channel_t *dch)
|
||||
{
|
||||
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
|
||||
del_timer(&dch->dbusytimer);
|
||||
if (test_bit(FLG_TX_BUSY, &dch->DFlags)) {
|
||||
if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
|
||||
del_timer(&dch->timer);
|
||||
if (test_bit(FLG_TX_BUSY, &dch->Flags)) {
|
||||
/* Restart frame */
|
||||
dch->tx_idx = 0;
|
||||
isac_fill_fifo(dch);
|
||||
} else if (dch->tx_skb) { /* should not happen */
|
||||
int_error();
|
||||
test_and_set_bit(FLG_TX_BUSY, &dch->Flags);
|
||||
dch->tx_idx = 0;
|
||||
isac_fill_fifo(dch);
|
||||
} else {
|
||||
printk(KERN_WARNING "mISDN: ISAC XDU no TX_BUSY\n");
|
||||
mISDN_debugprint(&dch->inst, "ISAC XDU no TX_BUSY");
|
||||
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) {
|
||||
if (test_bit(FLG_TX_NEXT, &dch->Flags)) {
|
||||
dch->tx_skb = dch->next_skb;
|
||||
if (dch->tx_skb) {
|
||||
mISDN_head_t *hh = mISDN_HEAD_P(dch->next_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);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
dch->tx_idx = 0;
|
||||
queue_ch_frame(dch, CONFIRM, hh->dinfo, NULL);
|
||||
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();
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
} else {
|
||||
printk(KERN_WARNING "isac xdu irq TX_NEXT without skb\n");
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
isac_mos_irq(dchannel_t *dch)
|
||||
isac_mos_irq(channel_t *dch)
|
||||
{
|
||||
u_char val;
|
||||
isac_chip_t *isac = dch->hw;
|
||||
|
@ -424,7 +423,7 @@ AfterMOX1:
|
|||
}
|
||||
|
||||
static void
|
||||
isac_cisq_irq(dchannel_t *dch) {
|
||||
isac_cisq_irq(channel_t *dch) {
|
||||
unsigned char val;
|
||||
|
||||
val = dch->read_reg(dch->inst.privat, ISAC_CIR0);
|
||||
|
@ -433,8 +432,8 @@ isac_cisq_irq(dchannel_t *dch) {
|
|||
if (val & 2) {
|
||||
if (dch->debug & L1_DEB_ISAC)
|
||||
mISDN_debugprint(&dch->inst, "ph_state change %x->%x",
|
||||
dch->ph_state, (val >> 2) & 0xf);
|
||||
dch->ph_state = (val >> 2) & 0xf;
|
||||
dch->state, (val >> 2) & 0xf);
|
||||
dch->state = (val >> 2) & 0xf;
|
||||
isac_ph_state_change(dch);
|
||||
}
|
||||
if (val & 1) {
|
||||
|
@ -445,7 +444,7 @@ isac_cisq_irq(dchannel_t *dch) {
|
|||
}
|
||||
|
||||
static void
|
||||
isacsx_cic_irq(dchannel_t *dch)
|
||||
isacsx_cic_irq(channel_t *dch)
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
|
@ -455,14 +454,14 @@ isacsx_cic_irq(dchannel_t *dch)
|
|||
if (val & ISACSX_CIR0_CIC0) {
|
||||
if (dch->debug & L1_DEB_ISAC)
|
||||
mISDN_debugprint(&dch->inst, "ph_state change %x->%x",
|
||||
dch->ph_state, val >> 4);
|
||||
dch->ph_state = val >> 4;
|
||||
dch->state, val >> 4);
|
||||
dch->state = val >> 4;
|
||||
isac_ph_state_change(dch);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
isacsx_rme_irq(dchannel_t *dch)
|
||||
isacsx_rme_irq(channel_t *dch)
|
||||
{
|
||||
int count;
|
||||
unsigned char val;
|
||||
|
@ -501,7 +500,7 @@ isacsx_rme_irq(dchannel_t *dch)
|
|||
}
|
||||
|
||||
void
|
||||
mISDN_isac_interrupt(dchannel_t *dch, u_char val)
|
||||
mISDN_isac_interrupt(channel_t *dch, u_char val)
|
||||
{
|
||||
if (dch->debug & L1_DEB_ISAC)
|
||||
mISDN_debugprint(&dch->inst, "ISAC interrupt %02x", val);
|
||||
|
@ -578,44 +577,22 @@ mISDN_isac_interrupt(dchannel_t *dch, u_char val)
|
|||
int
|
||||
mISDN_ISAC_l1hw(mISDNinstance_t *inst, struct sk_buff *skb)
|
||||
{
|
||||
dchannel_t *dch;
|
||||
channel_t *dch;
|
||||
int ret = 0;
|
||||
mISDN_head_t *hh;
|
||||
u_long flags;
|
||||
|
||||
hh = mISDN_HEAD_P(skb);
|
||||
dch = container_of(inst, dchannel_t, inst);
|
||||
dch = container_of(inst, channel_t, inst);
|
||||
if (hh->prim == PH_DATA_REQ) {
|
||||
/* check oversize */
|
||||
if (skb->len <= 0) {
|
||||
printk(KERN_WARNING "%s: skb too small\n", __FUNCTION__);
|
||||
return(-EINVAL);
|
||||
}
|
||||
if (skb->len > MAX_DFRAME_LEN_L1) {
|
||||
printk(KERN_WARNING "%s: skb too large\n", __FUNCTION__);
|
||||
return(-EINVAL);
|
||||
}
|
||||
spin_lock_irqsave(inst->hwlock, flags);
|
||||
if (dch->next_skb) {
|
||||
mISDN_debugprint(&dch->inst, " l2l1 next_skb exist this shouldn't happen");
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
return(-EBUSY);
|
||||
}
|
||||
if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) {
|
||||
test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
|
||||
dch->next_skb = skb;
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
return(0);
|
||||
} else {
|
||||
dch->tx_len = skb->len;
|
||||
memcpy(dch->tx_buf, skb->data, dch->tx_len);
|
||||
dch->tx_idx = 0;
|
||||
ret = channel_senddata(dch, hh->dinfo, skb);
|
||||
if (ret > 0) { /* direct TX */
|
||||
isac_fill_fifo(dch);
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
skb_trim(skb, 0);
|
||||
return(mISDN_queueup_newhead(inst, 0, PH_DATA_CNF,
|
||||
hh->dinfo, skb));
|
||||
ret = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
return(ret);
|
||||
} else if (hh->prim == (PH_SIGNAL | REQUEST)) {
|
||||
spin_lock_irqsave(inst->hwlock, flags);
|
||||
if (hh->dinfo == INFO3_P8)
|
||||
|
@ -628,9 +605,9 @@ mISDN_ISAC_l1hw(mISDNinstance_t *inst, struct sk_buff *skb)
|
|||
} else if (hh->prim == (PH_CONTROL | REQUEST)) {
|
||||
spin_lock_irqsave(inst->hwlock, flags);
|
||||
if (hh->dinfo == HW_RESET) {
|
||||
if ((dch->ph_state == ISAC_IND_EI) ||
|
||||
(dch->ph_state == ISAC_IND_DR) ||
|
||||
(dch->ph_state == ISAC_IND_RS))
|
||||
if ((dch->state == ISAC_IND_EI) ||
|
||||
(dch->state == ISAC_IND_DR) ||
|
||||
(dch->state == ISAC_IND_RS))
|
||||
ph_command(dch, ISAC_CMD_TIM);
|
||||
else
|
||||
ph_command(dch, ISAC_CMD_RS);
|
||||
|
@ -641,10 +618,10 @@ mISDN_ISAC_l1hw(mISDNinstance_t *inst, struct sk_buff *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);
|
||||
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
|
||||
del_timer(&dch->dbusytimer);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
|
||||
if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
|
||||
del_timer(&dch->timer);
|
||||
} else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) {
|
||||
u_char tl;
|
||||
if (dch->type & ISAC_TYPE_ISACSX) {
|
||||
|
@ -703,12 +680,12 @@ mISDN_ISAC_l1hw(mISDNinstance_t *inst, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
void
|
||||
mISDN_isac_free(dchannel_t *dch) {
|
||||
mISDN_isac_free(channel_t *dch) {
|
||||
isac_chip_t *isac = dch->hw;
|
||||
|
||||
if (dch->dbusytimer.function != NULL) {
|
||||
del_timer(&dch->dbusytimer);
|
||||
dch->dbusytimer.function = NULL;
|
||||
if (dch->timer.function != NULL) {
|
||||
del_timer(&dch->timer);
|
||||
dch->timer.function = NULL;
|
||||
}
|
||||
if (!isac)
|
||||
return;
|
||||
|
@ -719,12 +696,12 @@ mISDN_isac_free(dchannel_t *dch) {
|
|||
}
|
||||
|
||||
static void
|
||||
dbusy_timer_handler(dchannel_t *dch)
|
||||
dbusy_timer_handler(channel_t *dch)
|
||||
{
|
||||
int rbch, star;
|
||||
u_long flags;
|
||||
|
||||
if (test_bit(FLG_DBUSY_TIMER, &dch->DFlags)) {
|
||||
if (test_bit(FLG_BUSY_TIMER, &dch->Flags)) {
|
||||
spin_lock_irqsave(dch->inst.hwlock, flags);
|
||||
rbch = dch->read_reg(dch->inst.privat, ISAC_RBCH);
|
||||
star = dch->read_reg(dch->inst.privat, ISAC_STAR);
|
||||
|
@ -732,10 +709,10 @@ dbusy_timer_handler(dchannel_t *dch)
|
|||
mISDN_debugprint(&dch->inst, "D-Channel Busy RBCH %02x STAR %02x",
|
||||
rbch, star);
|
||||
if (rbch & ISAC_RBCH_XAC) { /* D-Channel Busy */
|
||||
test_and_set_bit(FLG_L1_DBUSY, &dch->DFlags);
|
||||
test_and_set_bit(FLG_L1_BUSY, &dch->Flags);
|
||||
} else {
|
||||
/* discard frame; reset transceiver */
|
||||
test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags);
|
||||
test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags);
|
||||
if (dch->tx_idx) {
|
||||
dch->tx_idx = 0;
|
||||
} else {
|
||||
|
@ -754,7 +731,7 @@ static char *ISACVer[] =
|
|||
"2085 V2.3"};
|
||||
|
||||
int
|
||||
mISDN_isac_init(dchannel_t *dch)
|
||||
mISDN_isac_init(channel_t *dch)
|
||||
{
|
||||
isac_chip_t *isac = dch->hw;
|
||||
u_char val;
|
||||
|
@ -762,12 +739,11 @@ mISDN_isac_init(dchannel_t *dch)
|
|||
|
||||
if (!isac)
|
||||
return(-EINVAL);
|
||||
dch->hw_bh = NULL;
|
||||
isac->mon_tx = NULL;
|
||||
isac->mon_rx = NULL;
|
||||
dch->dbusytimer.function = (void *) dbusy_timer_handler;
|
||||
dch->dbusytimer.data = (long) dch;
|
||||
init_timer(&dch->dbusytimer);
|
||||
dch->timer.function = (void *) dbusy_timer_handler;
|
||||
dch->timer.data = (long) dch;
|
||||
init_timer(&dch->timer);
|
||||
isac->mocr = 0xaa;
|
||||
if (dch->type & ISAC_TYPE_ISACSX) {
|
||||
// clear LDD
|
||||
|
@ -815,7 +791,7 @@ mISDN_isac_init(dchannel_t *dch)
|
|||
}
|
||||
|
||||
void
|
||||
mISDN_clear_isac(dchannel_t *dch)
|
||||
mISDN_clear_isac(channel_t *dch)
|
||||
{
|
||||
isac_chip_t *isac = dch->hw;
|
||||
u_int val, eval;
|
||||
|
@ -838,7 +814,7 @@ mISDN_clear_isac(dchannel_t *dch)
|
|||
}
|
||||
val = dch->read_reg(dch->inst.privat, ISAC_CIR0);
|
||||
mISDN_debugprint(&dch->inst, "ISAC CIR0 %x", val);
|
||||
dch->ph_state = (val >> 2) & 0xf;
|
||||
dch->state = (val >> 2) & 0xf;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
|
|
|
@ -128,9 +128,9 @@ typedef struct isac_chip {
|
|||
|
||||
/* interface for the isac module */
|
||||
|
||||
extern int mISDN_isac_init(dchannel_t *);
|
||||
extern void mISDN_isac_free(dchannel_t *);
|
||||
extern int mISDN_isac_init(channel_t *);
|
||||
extern void mISDN_isac_free(channel_t *);
|
||||
|
||||
extern void mISDN_isac_interrupt(dchannel_t *, u_char);
|
||||
extern void mISDN_clear_isac(dchannel_t *);
|
||||
extern void mISDN_isac_interrupt(channel_t *, u_char);
|
||||
extern void mISDN_clear_isac(channel_t *);
|
||||
extern int mISDN_ISAC_l1hw(mISDNinstance_t *, struct sk_buff *);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -230,9 +230,9 @@ typedef struct _isar_hw {
|
|||
#define STFAX_ESCAPE 5
|
||||
#define STFAX_SILDET 6
|
||||
|
||||
extern int ISARVersion(bchannel_t *bch, char *s);
|
||||
extern void isar_int_main(bchannel_t *bch);
|
||||
extern int init_isar(bchannel_t *bch);
|
||||
extern void free_isar(bchannel_t *bch);
|
||||
extern int ISARVersion(channel_t *bch, char *s);
|
||||
extern void isar_int_main(channel_t *bch);
|
||||
extern int init_isar(channel_t *bch);
|
||||
extern void free_isar(channel_t *bch);
|
||||
extern int isar_down(mISDNinstance_t *, struct sk_buff *);
|
||||
extern int isar_load_firmware(bchannel_t *bch, u_char *buf, int size);
|
||||
extern int isar_load_firmware(channel_t *bch, u_char *buf, int size);
|
||||
|
|
|
@ -36,8 +36,7 @@
|
|||
#else
|
||||
#include <linux/isapnp.h>
|
||||
#endif
|
||||
#include "dchannel.h"
|
||||
#include "bchannel.h"
|
||||
#include "channel.h"
|
||||
#include "isac.h"
|
||||
#include "isar.h"
|
||||
#include "layer1.h"
|
||||
|
@ -127,8 +126,8 @@ typedef struct _sedl_fax {
|
|||
isar_reg_t ir;
|
||||
isac_chip_t isac_hw;
|
||||
isar_hw_t isar_hw[2];
|
||||
dchannel_t dch;
|
||||
bchannel_t bch[2];
|
||||
channel_t dch;
|
||||
channel_t bch[2];
|
||||
} sedl_fax;
|
||||
|
||||
static inline u_char
|
||||
|
@ -193,25 +192,27 @@ WriteISACfifo(void *p, u_char * data, int size)
|
|||
*/
|
||||
|
||||
static u_char
|
||||
ReadISAR(void *p, int mode, u_char offset)
|
||||
ReadISAR(void *p, u_char offset)
|
||||
{
|
||||
if (mode == 0)
|
||||
return (readreg(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isar, offset));
|
||||
else if (mode == 1)
|
||||
byteout(((sedl_fax *)p)->addr, offset);
|
||||
return(bytein(((sedl_fax *)p)->isar));
|
||||
return (readreg(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isar, offset));
|
||||
}
|
||||
|
||||
static void
|
||||
WriteISAR(void *p, int mode, u_char offset, u_char value)
|
||||
WriteISAR(void *p, u_char offset, u_char value)
|
||||
{
|
||||
if (mode == 0)
|
||||
writereg(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isar, offset, value);
|
||||
else {
|
||||
if (mode == 1)
|
||||
byteout(((sedl_fax *)p)->addr, offset);
|
||||
byteout(((sedl_fax *)p)->isar, value);
|
||||
}
|
||||
writereg(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isar, offset, value);
|
||||
}
|
||||
|
||||
static void
|
||||
ReadISARfifo(void *p, u_char * data, int size)
|
||||
{
|
||||
readfifo(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isar, ISAR_MBOX, data, size);
|
||||
}
|
||||
|
||||
static void
|
||||
WriteISARfifo(void *p, u_char * data, int size)
|
||||
{
|
||||
writefifo(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isar, ISAR_MBOX, data, size);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -287,7 +288,7 @@ static void
|
|||
enable_hwirq(sedl_fax *sf)
|
||||
{
|
||||
WriteISAC(sf, ISAC_MASK, 0);
|
||||
WriteISAR(sf, 0, ISAR_IRQBIT, ISAR_IRQMSK);
|
||||
WriteISAR(sf, ISAR_IRQBIT, ISAR_IRQMSK);
|
||||
if (sf->subtyp != SEDL_SPEEDFAX_ISA)
|
||||
byteout(sf->cfg + TIGER_AUX_IRQMASK, SEDL_TIGER_IRQ_BIT);
|
||||
}
|
||||
|
@ -296,7 +297,7 @@ static void
|
|||
disable_hwirq(sedl_fax *sf)
|
||||
{
|
||||
WriteISAC(sf, ISAC_MASK, 0xFF);
|
||||
WriteISAR(sf, 0, ISAR_IRQBIT, 0);
|
||||
WriteISAR(sf, ISAR_IRQBIT, 0);
|
||||
if (sf->subtyp != SEDL_SPEEDFAX_ISA)
|
||||
byteout(sf->cfg + TIGER_AUX_IRQMASK, 0);
|
||||
}
|
||||
|
@ -462,10 +463,14 @@ setup_speedfax(sedl_fax *sf)
|
|||
sf->isar_hw[1].reg = &sf->ir;
|
||||
sf->bch[0].hw = &sf->isar_hw[0];
|
||||
sf->bch[1].hw = &sf->isar_hw[1];
|
||||
sf->bch[0].Read_Reg = &ReadISAR;
|
||||
sf->bch[0].Write_Reg = &WriteISAR;
|
||||
sf->bch[1].Read_Reg = &ReadISAR;
|
||||
sf->bch[1].Write_Reg = &WriteISAR;
|
||||
sf->bch[0].read_reg = &ReadISAR;
|
||||
sf->bch[0].write_reg = &WriteISAR;
|
||||
sf->bch[0].read_fifo = &ReadISARfifo;
|
||||
sf->bch[0].write_fifo = &WriteISARfifo;
|
||||
sf->bch[1].read_reg = &ReadISAR;
|
||||
sf->bch[1].write_reg = &WriteISAR;
|
||||
sf->bch[1].read_fifo = &ReadISARfifo;
|
||||
sf->bch[1].write_fifo = &WriteISARfifo;
|
||||
spin_lock_irqsave(&sf->lock, flags);
|
||||
disable_hwirq(sf);
|
||||
ver = ISARVersion(&sf->bch[0], "Sedlbauer:");
|
||||
|
@ -492,9 +497,9 @@ release_card(sedl_fax *card) {
|
|||
free_isar(&card->bch[0]);
|
||||
mISDN_isac_free(&card->dch);
|
||||
release_sedlbauer(card);
|
||||
mISDN_free_bch(&card->bch[1]);
|
||||
mISDN_free_bch(&card->bch[0]);
|
||||
mISDN_free_dch(&card->dch);
|
||||
mISDN_freechannel(&card->bch[1]);
|
||||
mISDN_freechannel(&card->bch[0]);
|
||||
mISDN_freechannel(&card->dch);
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
speedfax.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
spin_lock_irqsave(&speedfax.lock, flags);
|
||||
|
@ -554,9 +559,9 @@ speedfax_manager(void *data, u_int prim, void *arg) {
|
|||
switch(prim) {
|
||||
case MGR_REGLAYER | CONFIRM:
|
||||
if (channel == 2)
|
||||
dch_set_para(&card->dch, &inst->st->para);
|
||||
mISDN_setpara(&card->dch, &inst->st->para);
|
||||
else
|
||||
bch_set_para(&card->bch[channel], &inst->st->para);
|
||||
mISDN_setpara(&card->bch[channel], &inst->st->para);
|
||||
break;
|
||||
case MGR_UNREGLAYER | REQUEST:
|
||||
if ((skb = create_link_skb(PH_CONTROL | REQUEST,
|
||||
|
@ -576,9 +581,9 @@ speedfax_manager(void *data, u_int prim, void *arg) {
|
|||
arg = NULL;
|
||||
case MGR_ADDSTPARA | INDICATION:
|
||||
if (channel == 2)
|
||||
dch_set_para(&card->dch, arg);
|
||||
mISDN_setpara(&card->dch, arg);
|
||||
else
|
||||
bch_set_para(&card->bch[channel], arg);
|
||||
mISDN_setpara(&card->bch[channel], arg);
|
||||
break;
|
||||
case MGR_RELEASE | INDICATION:
|
||||
if (channel == 2) {
|
||||
|
@ -672,7 +677,7 @@ static int __devinit setup_instance(sedl_fax *card)
|
|||
mISDN_init_instance(&card->dch.inst, &speedfax, card, mISDN_ISAC_l1hw);
|
||||
sprintf(card->dch.inst.name, "SpeedFax%d", sedl_cnt+1);
|
||||
mISDN_set_dchannel_pid(&pid, protocol[sedl_cnt], layermask[sedl_cnt]);
|
||||
mISDN_init_dch(&card->dch);
|
||||
mISDN_initchannel(&card->dch, MSK_INIT_DCHANNEL, MAX_DFRAME_LEN_L1);
|
||||
for (i=0; i<2; i++) {
|
||||
card->bch[i].channel = i;
|
||||
mISDN_init_instance(&card->bch[i].inst, &speedfax, card, isar_down);
|
||||
|
@ -681,15 +686,15 @@ static int __devinit setup_instance(sedl_fax *card)
|
|||
card->bch[i].debug = debug;
|
||||
card->bch[i].inst.class_dev.dev = dev;
|
||||
sprintf(card->bch[i].inst.name, "%s B%d", card->dch.inst.name, i+1);
|
||||
mISDN_init_bch(&card->bch[i]);
|
||||
mISDN_initchannel(&card->dch, MSK_INIT_BCHANNEL, MAX_DATA_MEM);
|
||||
}
|
||||
printk(KERN_DEBUG "sfax card %p dch %p bch1 %p bch2 %p\n",
|
||||
card, &card->dch, &card->bch[0], &card->bch[1]);
|
||||
err = setup_speedfax(card);
|
||||
if (err) {
|
||||
mISDN_free_dch(&card->dch);
|
||||
mISDN_free_bch(&card->bch[1]);
|
||||
mISDN_free_bch(&card->bch[0]);
|
||||
mISDN_freechannel(&card->dch);
|
||||
mISDN_freechannel(&card->bch[1]);
|
||||
mISDN_freechannel(&card->bch[0]);
|
||||
spin_lock_irqsave(&speedfax.lock, flags);
|
||||
list_del(&card->list);
|
||||
spin_unlock_irqrestore(&speedfax.lock, flags);
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "dchannel.h"
|
||||
#include "channel.h"
|
||||
#include "bchannel.h"
|
||||
#include "layer1.h"
|
||||
#include "helper.h"
|
||||
|
@ -60,7 +60,7 @@ typedef struct _w6692pci {
|
|||
u_char xaddr;
|
||||
u_char xdata;
|
||||
w6692_bc wbc[2];
|
||||
dchannel_t dch;
|
||||
channel_t dch;
|
||||
bchannel_t bch[2];
|
||||
} w6692pci;
|
||||
|
||||
|
@ -139,12 +139,12 @@ ph_command(w6692pci *card, u_char command)
|
|||
}
|
||||
|
||||
static void
|
||||
W6692_new_ph(dchannel_t *dch)
|
||||
W6692_new_ph(channel_t *dch)
|
||||
{
|
||||
u_int prim = PH_SIGNAL | INDICATION;
|
||||
u_int para = 0;
|
||||
|
||||
switch (dch->ph_state) {
|
||||
switch (dch->state) {
|
||||
case W_L1CMD_RST:
|
||||
ph_command(dch->hw, W_L1CMD_DRC);
|
||||
mISDN_queue_data(&dch->inst, FLG_MSG_UP, PH_CONTROL | INDICATION, HW_RESET, 0, NULL, 0);
|
||||
|
@ -182,7 +182,7 @@ W6692_new_ph(dchannel_t *dch)
|
|||
static void
|
||||
W6692_empty_Dfifo(w6692pci *card, int count)
|
||||
{
|
||||
dchannel_t *dch = &card->dch;
|
||||
channel_t *dch = &card->dch;
|
||||
u_char *ptr;
|
||||
|
||||
if ((dch->debug & L1_DEB_ISAC) && !(dch->debug & L1_DEB_ISAC_FIFO))
|
||||
|
@ -206,18 +206,18 @@ W6692_empty_Dfifo(w6692pci *card, int count)
|
|||
insb(card->addr + W_D_RFIFO, ptr, count);
|
||||
WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);
|
||||
if (dch->debug & L1_DEB_ISAC_FIFO) {
|
||||
char *t = dch->dlog;
|
||||
char *t = dch->log;
|
||||
|
||||
t += sprintf(t, "empty_Dfifo cnt %d", count);
|
||||
mISDN_QuickHex(t, ptr, count);
|
||||
mISDN_debugprint(&dch->inst, dch->dlog);
|
||||
mISDN_debugprint(&dch->inst, dch->log);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
W6692_fill_Dfifo(w6692pci *card)
|
||||
{
|
||||
dchannel_t *dch = &card->dch;
|
||||
channel_t *dch = &card->dch;
|
||||
int count;
|
||||
u_char *ptr;
|
||||
u_char cmd = W_D_CMDR_XMS;
|
||||
|
@ -225,67 +225,71 @@ W6692_fill_Dfifo(w6692pci *card)
|
|||
if ((dch->debug & L1_DEB_ISAC) && !(dch->debug & L1_DEB_ISAC_FIFO))
|
||||
mISDN_debugprint(&dch->inst, "fill_Dfifo");
|
||||
|
||||
count = dch->tx_len - dch->tx_idx;
|
||||
if (!dch->tx_skb)
|
||||
return;
|
||||
count = dch->tx_skb->len - dch->tx_idx;
|
||||
if (count <= 0)
|
||||
return;
|
||||
if (count > 32) {
|
||||
if (count > 32)
|
||||
count = 32;
|
||||
} else
|
||||
else
|
||||
cmd |= W_D_CMDR_XME;
|
||||
ptr = dch->tx_buf + dch->tx_idx;
|
||||
ptr = dch->tx_skb->data + dch->tx_idx;
|
||||
dch->tx_idx += count;
|
||||
outsb(card->addr + W_D_XFIFO, ptr, count);
|
||||
WriteW6692(card, W_D_CMDR, cmd);
|
||||
if (test_and_set_bit(FLG_DBUSY_TIMER, &dch->DFlags)) {
|
||||
if (test_and_set_bit(FLG_BUSY_TIMER, &dch->Flags)) {
|
||||
mISDN_debugprint(&dch->inst, "fill_Dfifo dbusytimer running");
|
||||
del_timer(&dch->dbusytimer);
|
||||
del_timer(&dch->timer);
|
||||
}
|
||||
init_timer(&dch->dbusytimer);
|
||||
dch->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
|
||||
add_timer(&dch->dbusytimer);
|
||||
init_timer(&dch->timer);
|
||||
dch->timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
|
||||
add_timer(&dch->timer);
|
||||
if (dch->debug & L1_DEB_ISAC_FIFO) {
|
||||
char *t = dch->dlog;
|
||||
char *t = dch->log;
|
||||
|
||||
t += sprintf(t, "fill_Dfifo cnt %d", count);
|
||||
mISDN_QuickHex(t, ptr, count);
|
||||
mISDN_debugprint(&dch->inst, dch->dlog);
|
||||
mISDN_debugprint(&dch->inst, dch->log);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
d_retransmit(w6692pci *card)
|
||||
{
|
||||
dchannel_t *dch = &card->dch;
|
||||
channel_t *dch = &card->dch;
|
||||
|
||||
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
|
||||
del_timer(&dch->dbusytimer);
|
||||
if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
|
||||
del_timer(&dch->timer);
|
||||
#ifdef FIXME
|
||||
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
|
||||
if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags))
|
||||
dchannel_sched_event(dch, D_CLEARBUSY);
|
||||
#endif
|
||||
if (test_bit(FLG_TX_BUSY, &dch->DFlags)) {
|
||||
if (test_bit(FLG_TX_BUSY, &dch->Flags)) {
|
||||
/* Restart frame */
|
||||
dch->tx_idx = 0;
|
||||
W6692_fill_Dfifo(card);
|
||||
} else if (dch->tx_skb) { /* should not happen */
|
||||
int_error();
|
||||
test_and_set_bit(FLG_TX_BUSY, &dch->Flags);
|
||||
dch->tx_idx = 0;
|
||||
W6692_fill_Dfifo(card);
|
||||
} else {
|
||||
printk(KERN_WARNING "mISDN: w6692 XDU no TX_BUSY\n");
|
||||
mISDN_debugprint(&dch->inst, "XDU no TX_BUSY");
|
||||
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);
|
||||
if (test_bit(FLG_TX_NEXT, &dch->Flags)) {
|
||||
dch->tx_skb = dch->next_skb;
|
||||
if (dch->tx_skb) {
|
||||
mISDN_head_t *hh = mISDN_HEAD_P(dch->tx_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);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
dch->tx_idx = 0;
|
||||
queue_ch_frame(dch, CONFIRM, hh->dinfo, NULL);
|
||||
W6692_fill_Dfifo(card);
|
||||
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);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -336,43 +340,44 @@ handle_rxD(w6692pci *card) {
|
|||
|
||||
static void
|
||||
handle_txD(w6692pci *card) {
|
||||
register dchannel_t *dch = &card->dch;
|
||||
register channel_t *dch = &card->dch;
|
||||
|
||||
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
|
||||
del_timer(&dch->dbusytimer);
|
||||
if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
|
||||
del_timer(&dch->timer);
|
||||
#ifdef FIXME
|
||||
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
|
||||
if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags))
|
||||
dchannel_sched_event(dch, D_CLEARBUSY);
|
||||
#endif
|
||||
if (dch->tx_idx < dch->tx_len) {
|
||||
if (dch->tx_skb && dch->tx_idx < dch->tx_skb->len) {
|
||||
W6692_fill_Dfifo(card);
|
||||
} else {
|
||||
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);
|
||||
if (dch->tx_skb)
|
||||
dev_kfree_skb(dch->tx_skb);
|
||||
if (test_bit(FLG_TX_NEXT, &dch->Flags)) {
|
||||
dch->tx_skb = dch->next_skb;
|
||||
if (dch->tx_skb) {
|
||||
mISDN_head_t *hh = mISDN_HEAD_P(dch->tx_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);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
dch->tx_idx = 0;
|
||||
queue_ch_frame(dch, CONFIRM, hh->dinfo, NULL);
|
||||
W6692_fill_Dfifo(card);
|
||||
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);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
|
||||
}
|
||||
} else
|
||||
test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
|
||||
} else {
|
||||
dch->tx_skb = NULL;
|
||||
test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_statusD(w6692pci *card) {
|
||||
register dchannel_t *dch = &card->dch;
|
||||
register channel_t *dch = &card->dch;
|
||||
u_char exval, v1, cir;
|
||||
|
||||
exval = ReadW6692(card, W_D_EXIR);
|
||||
|
@ -410,8 +415,8 @@ handle_statusD(w6692pci *card) {
|
|||
v1 = cir & W_CIR_COD_MASK;
|
||||
if (card->dch.debug & L1_DEB_ISAC)
|
||||
mISDN_debugprint(&card->dch.inst, "ph_state_change %x -> %x",
|
||||
dch->ph_state, v1);
|
||||
dch->ph_state = v1;
|
||||
dch->state, v1);
|
||||
dch->state = v1;
|
||||
if (card->led & W_LED1_S0STATUS) {
|
||||
switch (v1) {
|
||||
case W_L1IND_AI8:
|
||||
|
@ -830,13 +835,13 @@ w6692_interrupt(int intno, void *dev_id, struct pt_regs *regs)
|
|||
}
|
||||
|
||||
static void
|
||||
dbusy_timer_handler(dchannel_t *dch)
|
||||
dbusy_timer_handler(channel_t *dch)
|
||||
{
|
||||
w6692pci *card = dch->hw;
|
||||
int rbch, star;
|
||||
u_long flags;
|
||||
|
||||
if (test_bit(FLG_DBUSY_TIMER, &dch->DFlags)) {
|
||||
if (test_bit(FLG_BUSY_TIMER, &dch->Flags)) {
|
||||
spin_lock_irqsave(dch->inst.hwlock, flags);
|
||||
rbch = ReadW6692(card, W_D_RBCH);
|
||||
star = ReadW6692(card, W_D_STAR);
|
||||
|
@ -844,10 +849,10 @@ dbusy_timer_handler(dchannel_t *dch)
|
|||
mISDN_debugprint(&dch->inst, "D-Channel Busy RBCH %02x STAR %02x",
|
||||
rbch, star);
|
||||
if (star & W_D_STAR_XBZ) { /* D-Channel Busy */
|
||||
test_and_set_bit(FLG_L1_DBUSY, &dch->DFlags);
|
||||
test_and_set_bit(FLG_L1_BUSY, &dch->Flags);
|
||||
} else {
|
||||
/* discard frame; reset transceiver */
|
||||
test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags);
|
||||
test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags);
|
||||
if (dch->tx_idx) {
|
||||
dch->tx_idx = 0;
|
||||
} else {
|
||||
|
@ -865,10 +870,9 @@ void initW6692(w6692pci *card)
|
|||
{
|
||||
u_char val;
|
||||
|
||||
card->dch.hw_bh = W6692_new_ph;
|
||||
card->dch.dbusytimer.function = (void *) dbusy_timer_handler;
|
||||
card->dch.dbusytimer.data = (u_long) &card->dch;
|
||||
init_timer(&card->dch.dbusytimer);
|
||||
card->dch.timer.function = (void *) dbusy_timer_handler;
|
||||
card->dch.timer.data = (u_long) &card->dch;
|
||||
init_timer(&card->dch.timer);
|
||||
mode_w6692(&card->bch[0], 0, -1);
|
||||
mode_w6692(&card->bch[1], 1, -1);
|
||||
WriteW6692(card, W_D_CTL, 0x00);
|
||||
|
@ -876,7 +880,7 @@ void initW6692(w6692pci *card)
|
|||
WriteW6692(card, W_D_SAM, 0xff);
|
||||
WriteW6692(card, W_D_TAM, 0xff);
|
||||
WriteW6692(card, W_D_MODE, W_D_MODE_RACT);
|
||||
card->dch.ph_state = W_L1CMD_RST;
|
||||
card->dch.state = W_L1CMD_RST;
|
||||
ph_command(card, W_L1CMD_RST);
|
||||
ph_command(card, W_L1CMD_ECK);
|
||||
/* enable all IRQ but extern */
|
||||
|
@ -1092,7 +1096,7 @@ w6692_l2l1B(mISDNinstance_t *inst, struct sk_buff *skb)
|
|||
static int
|
||||
w6692_l1hwD(mISDNinstance_t *inst, struct sk_buff *skb)
|
||||
{
|
||||
dchannel_t *dch = container_of(inst, dchannel_t, inst);
|
||||
channel_t *dch = container_of(inst, channel_t, inst);
|
||||
int ret = 0;
|
||||
mISDN_head_t *hh = mISDN_HEAD_P(skb);
|
||||
u_long flags;
|
||||
|
@ -1114,20 +1118,17 @@ w6692_l1hwD(mISDNinstance_t *inst, struct sk_buff *skb)
|
|||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
return(-EBUSY);
|
||||
}
|
||||
if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) {
|
||||
test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
|
||||
if (test_and_set_bit(FLG_TX_BUSY, &dch->Flags)) {
|
||||
test_and_set_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
dch->next_skb = skb;
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
return(0);
|
||||
} else {
|
||||
dch->tx_len = skb->len;
|
||||
memcpy(dch->tx_buf, skb->data, dch->tx_len);
|
||||
dch->tx_skb = skb;
|
||||
dch->tx_idx = 0;
|
||||
queue_ch_frame(dch, CONFIRM, hh->dinfo, NULL);
|
||||
W6692_fill_Dfifo(dch->hw);
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
return(mISDN_queueup_newhead(inst, 0, PH_DATA_CNF,
|
||||
hh->dinfo, skb));
|
||||
}
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
return(0);
|
||||
} else if (hh->prim == (PH_SIGNAL | REQUEST)) {
|
||||
spin_lock_irqsave(inst->hwlock, flags);
|
||||
if (hh->dinfo == INFO3_P8)
|
||||
|
@ -1140,7 +1141,7 @@ w6692_l1hwD(mISDNinstance_t *inst, struct sk_buff *skb)
|
|||
} else if (hh->prim == (PH_CONTROL | REQUEST)) {
|
||||
spin_lock_irqsave(inst->hwlock, flags);
|
||||
if (hh->dinfo == HW_RESET) {
|
||||
if (dch->ph_state != W_L1IND_DRD)
|
||||
if (dch->state != W_L1IND_DRD)
|
||||
ph_command(dch->hw, W_L1CMD_RST);
|
||||
ph_command(dch->hw, W_L1CMD_ECK);
|
||||
} else if (hh->dinfo == HW_POWERUP) {
|
||||
|
@ -1150,12 +1151,12 @@ w6692_l1hwD(mISDNinstance_t *inst, struct sk_buff *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);
|
||||
if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
|
||||
del_timer(&dch->dbusytimer);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
|
||||
if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
|
||||
del_timer(&dch->timer);
|
||||
#ifdef FIXME
|
||||
if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
|
||||
if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags))
|
||||
dchannel_sched_event(dch, D_CLEARBUSY);
|
||||
#endif
|
||||
} else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) {
|
||||
|
@ -1235,7 +1236,7 @@ release_card(w6692pci *card)
|
|||
release_region(card->addr, 256);
|
||||
mISDN_free_bch(&card->bch[1]);
|
||||
mISDN_free_bch(&card->bch[0]);
|
||||
mISDN_free_dch(&card->dch);
|
||||
mISDN_freechannel(&card->dch);
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
w6692.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
spin_lock_irqsave(&w6692.lock, flags);
|
||||
|
@ -1288,7 +1289,7 @@ w6692_manager(void *data, u_int prim, void *arg) {
|
|||
switch(prim) {
|
||||
case MGR_REGLAYER | CONFIRM:
|
||||
if (channel == 2)
|
||||
dch_set_para(&card->dch, &inst->st->para);
|
||||
mISDN_setpara(&card->dch, &inst->st->para);
|
||||
else
|
||||
bch_set_para(&card->bch[channel], &inst->st->para);
|
||||
break;
|
||||
|
@ -1310,7 +1311,7 @@ w6692_manager(void *data, u_int prim, void *arg) {
|
|||
arg = NULL;
|
||||
case MGR_ADDSTPARA | INDICATION:
|
||||
if (channel == 2)
|
||||
dch_set_para(&card->dch, arg);
|
||||
mISDN_setpara(&card->dch, arg);
|
||||
else
|
||||
bch_set_para(&card->bch[channel], arg);
|
||||
break;
|
||||
|
@ -1376,7 +1377,7 @@ static int __devinit setup_instance(w6692pci *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);
|
||||
mISDN_initchannel(&card->dch, MSK_DCHANNEL, MAX_DFRAME_LEN_L1);
|
||||
card->dch.hw = card;
|
||||
for (i=0; i<2; i++) {
|
||||
card->bch[i].channel = i;
|
||||
|
@ -1394,7 +1395,7 @@ static int __devinit setup_instance(w6692pci *card)
|
|||
card, &card->dch, &card->bch[0], &card->bch[1]);
|
||||
err = setup_w6692(card);
|
||||
if (err) {
|
||||
mISDN_free_dch(&card->dch);
|
||||
mISDN_freechannel(&card->dch);
|
||||
mISDN_free_bch(&card->bch[1]);
|
||||
mISDN_free_bch(&card->bch[0]);
|
||||
list_del(&card->list);
|
||||
|
|
|
@ -92,7 +92,7 @@ static void release_card(xhfc_hw * hw);
|
|||
/* Physical S/U commands to control Line Interface */
|
||||
/****************************************************/
|
||||
static void
|
||||
xhfc_ph_command(dchannel_t * dch, u_char command)
|
||||
xhfc_ph_command(channel_t * dch, u_char command)
|
||||
{
|
||||
xhfc_hw *hw = dch->hw;
|
||||
__u8 pt = hw->chan[dch->channel].port;
|
||||
|
@ -288,7 +288,7 @@ l1_timer_expire_t4(dchannel_t * dch)
|
|||
/* Line Interface State handler */
|
||||
/*********************************/
|
||||
static void
|
||||
su_new_state(dchannel_t * dch)
|
||||
su_new_state(channel_t * dch)
|
||||
{
|
||||
u_int prim = 0;
|
||||
|
||||
|
@ -299,18 +299,16 @@ su_new_state(dchannel_t * dch)
|
|||
|
||||
if (hw->port[pt].mode & PORT_MODE_TE) {
|
||||
if ((dch->debug) & (debug & DEBUG_HFC_S0_STATES))
|
||||
mISDN_debugprint(&dch->inst,
|
||||
"%s: TE %d",
|
||||
__FUNCTION__, dch->ph_state);
|
||||
mISDN_debugprint(&dch->inst, "%s: TE %d",
|
||||
__FUNCTION__, dch->state);
|
||||
|
||||
|
||||
if (dch->ph_state < 4 || dch->ph_state >= 7)
|
||||
if (dch->state < 4 || dch->state >= 7)
|
||||
l1_timer_stop_t3(dch);
|
||||
|
||||
if (dch->ph_state >= 7)
|
||||
if (dch->state >= 7)
|
||||
l1_timer_stop_t4(dch);
|
||||
|
||||
switch (dch->ph_state) {
|
||||
switch (dch->state) {
|
||||
case (0):
|
||||
case (1):
|
||||
case (2):
|
||||
|
@ -371,11 +369,10 @@ su_new_state(dchannel_t * dch)
|
|||
} else if (hw->port[pt].mode & PORT_MODE_NT) {
|
||||
|
||||
if ((dch->debug) & (debug & DEBUG_HFC_S0_STATES))
|
||||
mISDN_debugprint(&dch->inst,
|
||||
"%s: NT %d",
|
||||
__FUNCTION__, dch->ph_state);
|
||||
mISDN_debugprint(&dch->inst, "%s: NT %d",
|
||||
__FUNCTION__, dch->state);
|
||||
|
||||
switch (dch->ph_state) {
|
||||
switch (dch->state) {
|
||||
|
||||
case (1):
|
||||
dch->l1_up = 0;
|
||||
|
@ -435,7 +432,7 @@ su_new_state(dchannel_t * dch)
|
|||
static int
|
||||
xhfc_l1_from_up(mISDNinstance_t *inst, struct sk_buff *skb)
|
||||
{
|
||||
dchannel_t *dch = container_of(inst, dchannel_t, inst);
|
||||
channel_t *dch = container_of(inst, channel_t, inst);
|
||||
int ret = 0;
|
||||
mISDN_head_t *hh = mISDN_HEAD_P(skb);
|
||||
xhfc_hw *hw = inst->privat;
|
||||
|
@ -497,7 +494,7 @@ xhfc_l1_from_up(mISDNinstance_t *inst, struct sk_buff *skb)
|
|||
/* check for pending next_skb */
|
||||
spin_lock_irqsave(inst->hwlock, flags);
|
||||
if (dch->next_skb) {
|
||||
test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
|
||||
test_and_set_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
dch->next_skb = skb;
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
mISDN_debugprint(&dch->inst, "pending dch->next_skb!\n");
|
||||
|
@ -505,13 +502,13 @@ xhfc_l1_from_up(mISDNinstance_t *inst, struct sk_buff *skb)
|
|||
return (0);
|
||||
}
|
||||
|
||||
if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) {
|
||||
if (test_and_set_bit(FLG_TX_BUSY, &dch->Flags)) {
|
||||
if ((dch->debug) && (debug & DEBUG_HFC_DTRACE)) {
|
||||
mISDN_debugprint(&dch->inst, "channel(%i) busy, attaching dch->next_skb!\n",
|
||||
dch->channel,
|
||||
dch->channel,
|
||||
skb->len);
|
||||
}
|
||||
test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
|
||||
test_and_set_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
dch->next_skb = skb;
|
||||
spin_unlock_irqrestore(inst->hwlock, flags);
|
||||
return (0);
|
||||
|
@ -684,7 +681,7 @@ xhfc_manager(void *data, u_int prim, void *arg)
|
|||
struct sk_buff *skb;
|
||||
int channel = -1;
|
||||
int i;
|
||||
dchannel_t *dch = NULL;
|
||||
channel_t *dch = NULL;
|
||||
bchannel_t *bch = NULL;
|
||||
u_long flags;
|
||||
|
||||
|
@ -730,7 +727,7 @@ xhfc_manager(void *data, u_int prim, void *arg)
|
|||
switch (prim) {
|
||||
case MGR_REGLAYER | CONFIRM:
|
||||
if (dch)
|
||||
dch_set_para(dch, &inst->st->para);
|
||||
mISDN_setpara(dch, &inst->st->para);
|
||||
if (bch)
|
||||
bch_set_para(bch, &inst->st->para);
|
||||
break;
|
||||
|
@ -752,7 +749,7 @@ xhfc_manager(void *data, u_int prim, void *arg)
|
|||
arg = NULL;
|
||||
case MGR_ADDSTPARA | INDICATION:
|
||||
if (dch)
|
||||
dch_set_para(dch, arg);
|
||||
mISDN_setpara(dch, arg);
|
||||
if (bch)
|
||||
bch_set_para(bch, arg);
|
||||
break;
|
||||
|
@ -808,32 +805,29 @@ xhfc_manager(void *data, u_int prim, void *arg)
|
|||
int
|
||||
next_d_tx_frame(xhfc_hw * hw, __u8 channel)
|
||||
{
|
||||
dchannel_t *dch = hw->chan[channel].dch;
|
||||
channel_t *dch = hw->chan[channel].dch;
|
||||
|
||||
if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
|
||||
struct sk_buff *skb = dch->next_skb;
|
||||
|
||||
if (skb) {
|
||||
mISDN_head_t *hh = mISDN_HEAD_P(skb);
|
||||
if(dch->tx_skb)
|
||||
dev_kfree_skb(dch->tx_skb);
|
||||
if (test_and_clear_bit(FLG_TX_NEXT, &dch->Flags)) {
|
||||
dch->tx_skb = dch->next_skb;
|
||||
if (dch->tx_skb) {
|
||||
mISDN_head_t *hh = mISDN_HEAD_P(dch->tx_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);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
dch->tx_idx = 0;
|
||||
skb_trim(skb, 0);
|
||||
if (mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_CNF, hh->dinfo, skb))
|
||||
dev_kfree_skb(skb);
|
||||
queue_ch_frame(dch, CONFIRM, hh->dinfo, NULL);
|
||||
return (1);
|
||||
} else {
|
||||
printk(KERN_WARNING
|
||||
"%s channel(%i) TX_NEXT without skb\n",
|
||||
hw->card_name, channel);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
|
||||
test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &dch->Flags);
|
||||
test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
|
||||
}
|
||||
} else {
|
||||
test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
|
||||
dch->tx_skb = NULL;
|
||||
test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
@ -910,7 +904,7 @@ void
|
|||
xhfc_write_fifo(xhfc_hw * hw, __u8 channel)
|
||||
{
|
||||
__u8 *buf = NULL;
|
||||
int *len = NULL, *idx = NULL;
|
||||
int len = 0, *idx = NULL;
|
||||
mISDNinstance_t *inst = NULL;
|
||||
__u8 hdlc = 0;
|
||||
__u8 fcnt, tcnt, i;
|
||||
|
@ -919,21 +913,23 @@ xhfc_write_fifo(xhfc_hw * hw, __u8 channel)
|
|||
__u8 fstat;
|
||||
__u8 *data;
|
||||
|
||||
dchannel_t *dch = hw->chan[channel].dch;
|
||||
channel_t *dch = hw->chan[channel].dch;
|
||||
bchannel_t *bch = hw->chan[channel].bch;
|
||||
|
||||
/* get skb, fifo & mode */
|
||||
if (dch) {
|
||||
inst = &dch->inst;
|
||||
buf = dch->tx_buf;
|
||||
len = &dch->tx_len;
|
||||
if (!dch->tx_skb)
|
||||
return;
|
||||
buf = dch->tx_skb->data;
|
||||
len = dch->tx_skb->len;
|
||||
idx = &dch->tx_idx;
|
||||
hdlc = 1;
|
||||
}
|
||||
if (bch) {
|
||||
inst = &bch->inst;
|
||||
buf = bch->tx_buf;
|
||||
len = &bch->tx_len;
|
||||
len = bch->tx_len;
|
||||
idx = &bch->tx_idx;
|
||||
if (bch->protocol == ISDN_PID_L1_B_64HDLC)
|
||||
hdlc = 1;
|
||||
|
@ -948,12 +944,12 @@ xhfc_write_fifo(xhfc_hw * hw, __u8 channel)
|
|||
|
||||
send_buffer:
|
||||
|
||||
if (*len) {
|
||||
if (len) {
|
||||
xhfc_selfifo(hw, (channel * 2));
|
||||
|
||||
fstat = read_xhfc(hw, A_FIFO_STA);
|
||||
free = (hw->max_z - (read_xhfc(hw, A_USAGE)));
|
||||
tcnt = ((free >= (*len - *idx)) ? (*len - *idx) : free);
|
||||
tcnt = ((free >= (len - *idx)) ? (len - *idx) : free);
|
||||
|
||||
f1 = read_xhfc(hw, A_F1);
|
||||
f2 = read_xhfc(hw, A_F2);
|
||||
|
@ -963,7 +959,7 @@ xhfc_write_fifo(xhfc_hw * hw, __u8 channel)
|
|||
if (debug & DEBUG_HFC_FIFO) {
|
||||
mISDN_debugprint(inst,
|
||||
"%s channel(%i) len(%i) idx(%i) f1(%i) f2(%i) fcnt(%i) tcnt(%i) free(%i) fstat(%i)",
|
||||
__FUNCTION__, channel, *len, *idx,
|
||||
__FUNCTION__, channel, len, *idx,
|
||||
f1, f2, fcnt, tcnt, free, fstat);
|
||||
}
|
||||
|
||||
|
@ -1008,7 +1004,7 @@ xhfc_write_fifo(xhfc_hw * hw, __u8 channel)
|
|||
|
||||
|
||||
|
||||
if (*idx == *len) {
|
||||
if (*idx == len) {
|
||||
if (hdlc) {
|
||||
/* terminate frame */
|
||||
xhfc_inc_f(hw);
|
||||
|
@ -1037,49 +1033,45 @@ xhfc_write_fifo(xhfc_hw * hw, __u8 channel)
|
|||
}
|
||||
}
|
||||
|
||||
*len = 0;
|
||||
|
||||
len = 0;
|
||||
if (dch) {
|
||||
if (debug & DEBUG_HFC_DTRACE)
|
||||
mISDN_debugprint(&dch->
|
||||
inst,
|
||||
"TX frame channel(%i) completed",
|
||||
channel);
|
||||
mISDN_debugprint(&dch->inst,
|
||||
"TX frame channel(%i) completed",
|
||||
channel);
|
||||
|
||||
if (next_d_tx_frame(hw, channel)) {
|
||||
if (debug & DEBUG_HFC_DTRACE)
|
||||
mISDN_debugprint
|
||||
(&dch->inst,
|
||||
"channel(%i) has next_d_tx_frame",
|
||||
channel);
|
||||
mISDN_debugprint(&dch->inst,
|
||||
"channel(%i) has next_d_tx_frame",
|
||||
channel);
|
||||
buf = dch->tx_skb->data;
|
||||
len = dch->tx_skb->len;
|
||||
}
|
||||
}
|
||||
|
||||
if (bch) {
|
||||
if (debug & DEBUG_HFC_BTRACE)
|
||||
mISDN_debugprint(&bch->inst,
|
||||
"TX frame channel(%i) completed",
|
||||
channel);
|
||||
"TX frame channel(%i) completed",
|
||||
channel);
|
||||
|
||||
if (next_b_tx_frame(hw, channel)) {
|
||||
if (debug & DEBUG_HFC_BTRACE)
|
||||
mISDN_debugprint
|
||||
(&bch->inst,
|
||||
"channel(%i) has next_b_tx_frame",
|
||||
channel);
|
||||
|
||||
mISDN_debugprint(&bch->inst,
|
||||
"channel(%i) has next_b_tx_frame",
|
||||
channel);
|
||||
len = bch->tx_len;
|
||||
if ((free - tcnt) > 8) {
|
||||
if (debug & DEBUG_HFC_BTRACE)
|
||||
mISDN_debugprint
|
||||
(&bch->inst,
|
||||
"continue immediatetly",
|
||||
channel);
|
||||
mISDN_debugprint(&bch->inst,
|
||||
"continue immediatetly",
|
||||
channel);
|
||||
goto send_buffer;
|
||||
}
|
||||
}
|
||||
test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* tx buffer not complete, but fifo filled to maximum */
|
||||
xhfc_selfifo(hw, (channel * 2));
|
||||
|
@ -1107,7 +1099,7 @@ xhfc_read_fifo(xhfc_hw * hw, __u8 channel)
|
|||
struct sk_buff *skb; /* data buffer for upper layer */
|
||||
__u16 i;
|
||||
|
||||
dchannel_t *dch = hw->chan[channel].dch;
|
||||
channel_t *dch = hw->chan[channel].dch;
|
||||
bchannel_t *bch = hw->chan[channel].bch;
|
||||
|
||||
if (dch) {
|
||||
|
@ -1303,7 +1295,7 @@ static void
|
|||
xhfc_bh_handler(unsigned long ul_hw)
|
||||
{
|
||||
xhfc_hw *hw = (xhfc_hw *) ul_hw;
|
||||
dchannel_t *dch;
|
||||
channel_t *dch;
|
||||
int i;
|
||||
reg_a_su_rd_sta su_state;
|
||||
|
||||
|
@ -1321,7 +1313,7 @@ xhfc_bh_handler(unsigned long ul_hw)
|
|||
if (hw->chan[i].dch)
|
||||
if (test_bit
|
||||
(FLG_TX_BUSY,
|
||||
&hw->chan[i].dch->DFlags)) {
|
||||
&hw->chan[i].dch->Flags)) {
|
||||
xhfc_write_fifo(hw, i);
|
||||
}
|
||||
|
||||
|
@ -1371,8 +1363,8 @@ xhfc_bh_handler(unsigned long ul_hw)
|
|||
|
||||
dch = hw->chan[(i << 2) + 2].dch;
|
||||
if (dch) {
|
||||
if (su_state.bit.v_su_sta != dch->ph_state) {
|
||||
dch->ph_state = su_state.bit.v_su_sta;
|
||||
if (su_state.bit.v_su_sta != dch->state) {
|
||||
dch->state = su_state.bit.v_su_sta;
|
||||
su_new_state(dch);
|
||||
}
|
||||
}
|
||||
|
@ -1598,7 +1590,7 @@ release_channels(xhfc_hw * hw)
|
|||
printk(KERN_DEBUG
|
||||
"%s %s: free D-channel %d\n",
|
||||
hw->card_name, __FUNCTION__, i);
|
||||
mISDN_free_dch(hw->chan[i].dch);
|
||||
mISDN_freechannel(hw->chan[i].dch);
|
||||
hw_mISDNObj.ctrl(&hw->chan[i].dch->inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
kfree(hw->chan[i].dch);
|
||||
hw->chan[i].dch = NULL;
|
||||
|
@ -1866,7 +1858,7 @@ init_mISDN_channels(xhfc_hw * hw)
|
|||
int pt;
|
||||
int ch;
|
||||
int b;
|
||||
dchannel_t *dch;
|
||||
channel_t *dch;
|
||||
bchannel_t *bch;
|
||||
mISDN_pid_t pid;
|
||||
u_long flags;
|
||||
|
@ -1886,12 +1878,12 @@ init_mISDN_channels(xhfc_hw * hw)
|
|||
|
||||
hw->chan[ch].port = pt;
|
||||
|
||||
dch = kmalloc(sizeof(dchannel_t), GFP_ATOMIC);
|
||||
dch = kmalloc(sizeof(channel_t), GFP_ATOMIC);
|
||||
if (!dch) {
|
||||
err = -ENOMEM;
|
||||
goto free_channels;
|
||||
}
|
||||
memset(dch, 0, sizeof(dchannel_t));
|
||||
memset(dch, 0, sizeof(channel_t));
|
||||
dch->channel = ch;
|
||||
dch->debug = debug;
|
||||
dch->inst.obj = &hw_mISDNObj;
|
||||
|
@ -1907,11 +1899,9 @@ init_mISDN_channels(xhfc_hw * hw)
|
|||
err = -ENOMEM;
|
||||
goto free_channels;
|
||||
}
|
||||
|
||||
if (mISDN_init_dch(dch)) {
|
||||
err = -ENOMEM;
|
||||
err = mISDN_initchannel(dch, MSK_DCHANNEL, MAX_DFRAME_LEN_L1);
|
||||
if (err)
|
||||
goto free_channels;
|
||||
}
|
||||
dch->hw = hw;
|
||||
hw->chan[ch].dch = dch;
|
||||
|
||||
|
@ -2005,8 +1995,7 @@ init_mISDN_channels(xhfc_hw * hw)
|
|||
goto free_channels;
|
||||
}
|
||||
|
||||
dch->hw_bh = su_new_state;
|
||||
dch->ph_state = 0;
|
||||
dch->state = 0;
|
||||
|
||||
for (b = 0; b < 2; b++) {
|
||||
bch = hw->chan[(pt << 2) + b].bch;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#define _XHFC_SU_H_
|
||||
|
||||
#include <linux/timer.h>
|
||||
#include "dchannel.h"
|
||||
#include "channel.h"
|
||||
#include "bchannel.h"
|
||||
#include "xhfc24succ.h"
|
||||
|
||||
|
@ -119,7 +119,7 @@ typedef struct {
|
|||
/* channel struct for each fifo */
|
||||
typedef struct {
|
||||
bchannel_t *bch;
|
||||
dchannel_t *dch;
|
||||
channel_t *dch;
|
||||
int rx_idx; /* for D-channel */
|
||||
__u8 *rx_buf; /* for D-channel */
|
||||
int port; /* index pointer to port struct */
|
||||
|
|
Loading…
Reference in New Issue