Commit 7007e717 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: Make V.110 support less intrusive

It'd probably make more sense to provide it in library form
to the hardware drivers which don't support V.110 natively, but for
now it's at least collected in one place.
parent 0bba2356
This diff is collapsed.
...@@ -2314,6 +2314,7 @@ isdn_tty_find_icall(int di, int ch, int sl, setup_parm *setup) ...@@ -2314,6 +2314,7 @@ isdn_tty_find_icall(int di, int ch, int sl, setup_parm *setup)
static int static int
isdn_tty_stat_callback(int i, isdn_ctrl *c) isdn_tty_stat_callback(int i, isdn_ctrl *c)
{ {
isdn_ctrl cmd;
modem_info *info; modem_info *info;
char *e; char *e;
...@@ -2366,6 +2367,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c) ...@@ -2366,6 +2367,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
#endif #endif
if (TTY_IS_ACTIVE(info)) { if (TTY_IS_ACTIVE(info)) {
if (info->dialing == 1) { if (info->dialing == 1) {
isdn_slot_command(info->isdn_slot, ISDN_CMD_ACCEPTB, &cmd);
info->dialing = 2; info->dialing = 2;
return 1; return 1;
} }
......
...@@ -82,7 +82,7 @@ FlipBits(unsigned char c, int keylen) ...@@ -82,7 +82,7 @@ FlipBits(unsigned char c, int keylen)
* structures and returns a pointer to these. * structures and returns a pointer to these.
*/ */
static isdn_v110_stream * static isdn_v110_stream *
isdn_v110_open(unsigned char key, int hdrlen, int maxsize) do_isdn_v110_open(unsigned char key, int hdrlen, int maxsize)
{ {
int i; int i;
isdn_v110_stream *v; isdn_v110_stream *v;
...@@ -127,8 +127,8 @@ isdn_v110_open(unsigned char key, int hdrlen, int maxsize) ...@@ -127,8 +127,8 @@ isdn_v110_open(unsigned char key, int hdrlen, int maxsize)
} }
/* isdn_v110_close frees private V.110 data structures */ /* isdn_v110_close frees private V.110 data structures */
void static void
isdn_v110_close(isdn_v110_stream * v) do_isdn_v110_close(isdn_v110_stream * v)
{ {
if (v == NULL) if (v == NULL)
return; return;
...@@ -510,99 +510,94 @@ isdn_v110_encode(isdn_v110_stream * v, struct sk_buff *skb) ...@@ -510,99 +510,94 @@ isdn_v110_encode(isdn_v110_stream * v, struct sk_buff *skb)
return nskb; return nskb;
} }
void
isdn_v110_open(int sl, struct isdn_v110 *iv110)
{
isdn_v110_stream *v;
int hdrlen = isdn_slot_hdrlen(sl);
int maxsize = isdn_slot_maxbufsize(sl);
atomic_inc(&iv110->v110use);
switch (iv110->v110emu) {
case ISDN_PROTO_L2_V11096:
iv110->v110 = do_isdn_v110_open(V110_9600, hdrlen, maxsize);
break;
case ISDN_PROTO_L2_V11019:
iv110->v110 = do_isdn_v110_open(V110_19200, hdrlen, maxsize);
break;
case ISDN_PROTO_L2_V11038:
iv110->v110 = do_isdn_v110_open(V110_38400, hdrlen, maxsize);
break;
}
if ((v = iv110->v110)) {
while (v->SyncInit) {
struct sk_buff *skb = isdn_v110_sync(v);
if (isdn_slot_write(sl, skb) <= 0) {
dev_kfree_skb(skb);
/* Unable to send, try later */
break;
}
v->SyncInit--;
v->skbidle++;
}
} else
printk(KERN_WARNING "isdn_v110: Couldn't open stream\n");
atomic_dec(&iv110->v110use);
}
void
isdn_v110_close(int sl, struct isdn_v110 *iv110)
{
while (1) {
atomic_inc(&iv110->v110use);
if (atomic_dec_and_test(&iv110->v110use)) {
do_isdn_v110_close(iv110->v110);
iv110->v110 = NULL;
break;
}
}
}
int int
isdn_v110_stat_callback(int sl, struct isdn_v110 *iv110, isdn_ctrl *c) isdn_v110_bsent(int sl, struct isdn_v110 *iv110)
{ {
isdn_v110_stream *v = NULL; isdn_v110_stream *v = iv110->v110;
int i; int i, ret;
int ret;
/* Keep the send-queue of the driver filled
switch (c->command) { * with frames:
case ISDN_STAT_BSENT: * If number of outstanding frames < 3,
/* Keep the send-queue of the driver filled * send down an Idle-Frame (or an Sync-Frame, if
* with frames: * v->SyncInit != 0).
* If number of outstanding frames < 3, */
* send down an Idle-Frame (or an Sync-Frame, if atomic_inc(&iv110->v110use);
* v->SyncInit != 0). if (v->skbidle > 0) {
*/ v->skbidle--;
if (!(v = iv110->v110)) ret = 1;
return 0; } else {
atomic_inc(&iv110->v110use); if (v->skbuser > 0)
if (v->skbidle > 0) { v->skbuser--;
v->skbidle--; ret = 0;
ret = 1; }
for (i = v->skbuser + v->skbidle; i < 2; i++) {
struct sk_buff *skb;
if (v->SyncInit > 0)
skb = isdn_v110_sync(v);
else
skb = isdn_v110_idle(v);
if (skb) {
if (isdn_slot_write(sl, skb) <= 0) {
dev_kfree_skb(skb);
break;
} else { } else {
if (v->skbuser > 0) if (v->SyncInit)
v->skbuser--; v->SyncInit--;
ret = 0; v->skbidle++;
}
for (i = v->skbuser + v->skbidle; i < 2; i++) {
struct sk_buff *skb;
if (v->SyncInit > 0)
skb = isdn_v110_sync(v);
else
skb = isdn_v110_idle(v);
if (skb) {
if (isdn_slot_write(sl, skb) <= 0) {
dev_kfree_skb(skb);
break;
} else {
if (v->SyncInit)
v->SyncInit--;
v->skbidle++;
}
} else
break;
}
atomic_dec(&iv110->v110use);
return ret;
case ISDN_STAT_DHUP:
case ISDN_STAT_BHUP:
while (1) {
atomic_inc(&iv110->v110use);
if (atomic_dec_and_test(&iv110->v110use)) {
isdn_v110_close(iv110->v110);
iv110->v110 = NULL;
break;
}
sti();
} }
} else
break; break;
case ISDN_STAT_BCONN:
if (iv110->v110emu && (iv110->v110 == NULL)) {
int hdrlen = isdn_slot_hdrlen(sl);
int maxsize = isdn_slot_maxbufsize(sl);
atomic_inc(&iv110->v110use);
switch (iv110->v110emu) {
case ISDN_PROTO_L2_V11096:
iv110->v110 = isdn_v110_open(V110_9600, hdrlen, maxsize);
break;
case ISDN_PROTO_L2_V11019:
iv110->v110 = isdn_v110_open(V110_19200, hdrlen, maxsize);
break;
case ISDN_PROTO_L2_V11038:
iv110->v110 = isdn_v110_open(V110_38400, hdrlen, maxsize);
break;
default:;
}
if ((v = iv110->v110)) {
while (v->SyncInit) {
struct sk_buff *skb = isdn_v110_sync(v);
if (isdn_slot_write(sl, skb) <= 0) {
dev_kfree_skb(skb);
/* Unable to send, try later */
break;
}
v->SyncInit--;
v->skbidle++;
}
} else
printk(KERN_WARNING "isdn_v110: Couldn't open stream\n");
atomic_dec(&iv110->v110use);
}
break;
default:
return 0;
} }
return 0; atomic_dec(&iv110->v110use);
return ret;
} }
...@@ -26,7 +26,10 @@ extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *); ...@@ -26,7 +26,10 @@ extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *);
*/ */
extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *); extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *);
extern int isdn_v110_stat_callback(int sl, struct isdn_v110 *v110, isdn_ctrl *); extern void isdn_v110_open(int sl, struct isdn_v110 *iv110);
extern void isdn_v110_close(isdn_v110_stream * v);
extern void isdn_v110_close(int sl, struct isdn_v110 *iv110);
extern int isdn_v110_bsent(int sl, struct isdn_v110 *iv110);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment