]> git.neil.brown.name Git - history.git/commitdiff
ISDN: Make V.110 support less intrusive
authorKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>
Tue, 29 Oct 2002 14:52:15 +0000 (08:52 -0600)
committerKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>
Tue, 29 Oct 2002 14:52:15 +0000 (08:52 -0600)
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.

drivers/isdn/i4l/isdn_common.c
drivers/isdn/i4l/isdn_tty.c
drivers/isdn/i4l/isdn_v110.c
drivers/isdn/i4l/isdn_v110.h

index cb7c31f5bc9f9f664fa99883326a91177c6d33a1..e46f2d5285bad3f23d4c9cdbd65dc36c1104581e 100644 (file)
@@ -37,7 +37,6 @@ isdn_dev *dev;
 
 static void isdn_register_devfs(int);
 static void isdn_unregister_devfs(int);
-static int  isdn_drv_writebuf_skb(int di, int ch, int x, struct sk_buff *skb);
 
 /* ====================================================================== */
 
@@ -152,6 +151,13 @@ struct isdn_slot {
 
 static int __slot_command(struct isdn_slot *slot, isdn_ctrl *cmd);
 
+static void isdn_v110_setl2(struct isdn_slot *slot, isdn_ctrl *cmd);
+static void __isdn_v110_open(struct isdn_slot *slot);
+static void __isdn_v110_close(struct isdn_slot *slot);
+static void __isdn_v110_bsent(struct isdn_slot *slot, isdn_ctrl *cmd);
+static int  isdn_v110_data_ind(struct isdn_slot *slot, struct sk_buff *skb);
+static int  isdn_v110_data_req(struct isdn_slot *slot, struct sk_buff *skb);
+
 static inline int
 do_stat_cb(struct isdn_slot *slot, isdn_ctrl *ctrl)
 {
@@ -192,6 +198,18 @@ slot_stat(struct fsm_inst *fi, int pr, void *arg)
        return 0;
 }
 
+/* just pass through command */
+static int
+slot_setl2(struct fsm_inst *fi, int pr, void *arg)
+{
+       struct isdn_slot *slot = fi->userdata;
+       isdn_ctrl *c = arg;
+
+       isdn_v110_setl2(slot, c);
+
+       return __slot_command(slot, c);
+}
+
 static int
 slot_dial(struct fsm_inst *fi, int pr, void *arg)
 {
@@ -242,9 +260,9 @@ slot_actv_hangup(struct fsm_inst *fi, int pr, void *arg)
        int retval;
 
        retval = __slot_command(slot, ctrl);
-       if (retval >= 0)
+       if (retval >= 0) {
                fsm_change_state(fi, ST_SLOT_WAIT_BHUP);
-
+       }
        return retval;
 }
 
@@ -266,6 +284,7 @@ slot_bconn(struct fsm_inst *fi, int pr, void *arg)
        isdn_ctrl *ctrl = arg;
 
        fsm_change_state(fi, ST_SLOT_ACTIVE);
+       __isdn_v110_open(slot);
 
        isdn_info_update();
 
@@ -279,6 +298,7 @@ slot_bhup(struct fsm_inst *fi, int pr, void *arg)
        struct isdn_slot *slot = fi->userdata;
        isdn_ctrl *ctrl = arg;
 
+       __isdn_v110_close(slot);
        fsm_change_state(fi, ST_SLOT_WAIT_DHUP);
 
        do_stat_cb(slot, ctrl);
@@ -303,34 +323,19 @@ slot_data_req(struct fsm_inst *fi, int pr, void *arg)
        struct isdn_slot *slot = fi->userdata;
        struct sk_buff *skb = arg;
 
-       return isdn_drv_writebuf_skb(slot->di, slot->ch, 1, skb);
+       return isdn_v110_data_req(slot, skb);
 }
 
 static int
 slot_data_ind(struct fsm_inst *fi, int pr, void *arg)
 {
        struct isdn_slot *slot = fi->userdata;
-       int sl = slot - slots;
        struct sk_buff *skb = arg;
 
        /* Update statistics */
        slot->ibytes += skb->len;
-       slot->recv_cb(sl, skb);
-       return 0;
 
-#if 0
-       /* V.110 handling
-        * makes sense for async streams only, so it is
-        * called after possible net-device delivery.
-        */
-       if (slots[i].iv110.v110) {
-               atomic_inc(&slots[i].iv110.v110use);
-               skb = isdn_v110_decode(slots[i].iv110.v110, skb);
-               atomic_dec(&slots[i].iv110.v110use);
-               if (!skb)
-                       return;
-       }
-#endif
+       return isdn_v110_data_ind(slot, skb);
 }
 
 static int
@@ -339,7 +344,7 @@ slot_bsent(struct fsm_inst *fi, int pr, void *arg)
        struct isdn_slot *slot = fi->userdata;
        isdn_ctrl *ctrl = arg;
 
-       do_stat_cb(slot, ctrl);
+       __isdn_v110_bsent(slot, ctrl);
        return 0;
 }
 
@@ -391,12 +396,6 @@ slot_unbind(struct fsm_inst *fi, int pr, void *arg)
        strcpy(slot->num, "???");
        slot->ibytes = 0;
        slot->obytes = 0;
-// 20.10.99 JIM, try to reinitialize v110 !
-       slot->iv110.v110emu = 0;
-       atomic_set(&slot->iv110.v110use, 0);
-       isdn_v110_close(slot->iv110.v110);
-       slot->iv110.v110 = NULL;
-// 20.10.99 JIM, try to reinitialize v110 !
        slot->usage = ISDN_USAGE_NONE;
        isdn_info_update();
        return 0;
@@ -408,12 +407,12 @@ static struct fsm_node slot_fn_tbl[] = {
 
        { ST_SLOT_BOUND,         EV_CMD_CLREAZ,  slot_command     },
        { ST_SLOT_BOUND,         EV_CMD_SETEAZ,  slot_command     },
-       { ST_SLOT_BOUND,         EV_CMD_SETL2,   slot_command     },
+       { ST_SLOT_BOUND,         EV_CMD_SETL2,   slot_setl2       },
        { ST_SLOT_BOUND,         EV_CMD_SETL3,   slot_command     },
        { ST_SLOT_BOUND,         EV_CMD_DIAL,    slot_dial        },
        { ST_SLOT_BOUND,         EV_SLOT_UNBIND, slot_unbind      },
 
-       { ST_SLOT_IN,            EV_CMD_SETL2,   slot_command     },
+       { ST_SLOT_IN,            EV_CMD_SETL2,   slot_setl2       },
        { ST_SLOT_IN,            EV_CMD_SETL3,   slot_command     },
        { ST_SLOT_IN,            EV_CMD_ACCEPTD, slot_acceptd     },
        { ST_SLOT_IN,            EV_STAT_DHUP,   slot_in_dhup     },
@@ -488,6 +487,7 @@ struct isdn_driver {
        char                id[20];
        atomic_t            refcnt;
        unsigned long       flags;            /* Misc driver Flags           */
+       unsigned long       features;
        int                 locks;            /* Number of locks             */
        int                 channels;         /* Number of channels          */
        wait_queue_head_t   st_waitq;         /* Wait-Queue for status-reads */
@@ -504,26 +504,32 @@ static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED;
 static struct isdn_driver *drivers[ISDN_MAX_DRIVERS];
 
 static int
-isdn_drv_writebuf_skb(int di, int ch, int x, struct sk_buff *skb)
+isdn_writebuf_skb(struct isdn_slot *slot, struct sk_buff *skb)
 {
        struct sk_buff *skb2;
-       struct isdn_driver *drv = drivers[di];
+       struct isdn_driver *drv = slot->drv;
        int hl = drv->interface->hl_hdrlen;
        int retval;
 
-       if (skb_headroom(skb) >= hl)
-               return drivers[di]->interface->writebuf_skb(di, ch, 1, skb);
-
+       if (skb_headroom(skb) >= hl) {
+               retval = drv->interface->writebuf_skb(slot->di, slot->ch, 1, skb);
+               goto out;
+       }
        skb2 = skb_realloc_headroom(skb, hl);
-       if (!skb2)
-               return -ENOMEM;
-       
-       retval = drivers[di]->interface->writebuf_skb(di, ch, 1, skb2);
+       if (!skb2) {
+               retval = -ENOMEM;
+               goto out;
+       }
+       retval = drv->interface->writebuf_skb(slot->di, slot->ch, 1, skb2);
        if (retval < 0)
                kfree_skb(skb2);
        else
                kfree_skb(skb);
 
+ out:
+       if (retval > 0)
+               slots->obytes += retval;
+
        return retval;
 }
 
@@ -617,8 +623,9 @@ set_global_features(void)
        for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) {
                if (!drivers[drvidx])
                        continue;
-               if (drivers[drvidx]->interface)
-                       dev->global_features |= drivers[drvidx]->interface->features;
+               if (drivers[drvidx]->fi.state != ST_DRV_RUNNING)
+                       continue;
+               dev->global_features |= drivers[drvidx]->features;
        }
        spin_unlock_irqrestore(&drivers_lock, flags);
 }
@@ -630,6 +637,8 @@ static int  isdn_add_channels(struct isdn_driver *, int, int, int);
 static void isdn_receive_skb_callback(int di, int ch, struct sk_buff *skb);
 static int  isdn_status_callback(isdn_ctrl * c);
 
+static void isdn_v110_add_features(struct isdn_driver *drv);
+
 static int
 drv_register(struct fsm_inst *fi, int pr, void *arg)
 {
@@ -644,13 +653,16 @@ drv_register(struct fsm_inst *fi, int pr, void *arg)
        iif->statcallb = isdn_status_callback;
 
        isdn_info_update();
-       set_global_features();
 }
 
 static int
 drv_stat_run(struct fsm_inst *fi, int pr, void *arg)
 {
+       struct isdn_driver *drv = fi->userdata;
        fsm_change_state(fi, ST_DRV_RUNNING);
+
+       drv->features = drv->interface->features;
+       isdn_v110_add_features(drv);
        set_global_features();
 }
 
@@ -692,7 +704,6 @@ drv_stat_unload(struct fsm_inst *fi, int pr, void *arg)
        }
        dev->channels -= drv->channels;
 
-       set_global_features();
        isdn_info_update();
        return 0;
 }
@@ -879,7 +890,6 @@ isdn_status_callback(isdn_ctrl *c)
                        break;
 #if 0
                case ISDN_STAT_ICALL:
-                       isdn_v110_stat_callback(&slots[i].iv110, c);
                        /* Find any ttyI, waiting for D-channel setup */
                        if (isdn_tty_stat_callback(i, c)) {
                                cmd.driver = di;
@@ -928,15 +938,12 @@ isdn_status_callback(isdn_ctrl *c)
                        return retval;
                        break;
                case ISDN_STAT_DHUP:
-                       isdn_v110_stat_callback(&slots[i].iv110, c);
                         if (divert_if)
                                divert_if->stat_callback(c); 
                        break;
                case ISDN_STAT_BCONN:
-                       isdn_v110_stat_callback(&slots[i].iv110, c);
                        break;
                case ISDN_STAT_BHUP:
-                       isdn_v110_stat_callback(&slots[i].iv110, c);
                        break;
 #endif
 #if 0 // FIXME
@@ -1306,40 +1313,11 @@ __drv_command(struct isdn_driver *drv, isdn_ctrl *c)
        return drv->interface->command(c);
 }
 
-/*
- * Intercept command from Linklevel to Lowlevel.
- * If layer 2 protocol is V.110 and this is not supported by current
- * lowlevel-driver, use driver's transparent mode and handle V.110 in
- * linklevel instead.
- */
 static int
 __slot_command(struct isdn_slot *slot, isdn_ctrl *cmd)
 {
        struct isdn_driver *drv = slot->drv;
 
-       if (cmd->command == ISDN_CMD_SETL2) {
-               unsigned long l2prot = (cmd->arg >> 8) & 255;
-               unsigned long features = (drv->interface->features
-                                         >> ISDN_FEATURE_L2_SHIFT) &
-                                               ISDN_FEATURE_L2_MASK;
-               unsigned long l2_feature = 1 << l2prot;
-
-               switch (l2prot) {
-                       case ISDN_PROTO_L2_V11096:
-                       case ISDN_PROTO_L2_V11019:
-                       case ISDN_PROTO_L2_V11038:
-                       /* If V.110 requested, but not supported by
-                        * HL-driver, set emulator-flag and change
-                        * Layer-2 to transparent
-                        */
-                               if (!(features & l2_feature)) {
-                                       slot->iv110.v110emu = l2prot;
-                                       cmd->arg = (cmd->arg & 255) |
-                                               (ISDN_PROTO_L2_TRANS << 8);
-                               } else
-                                       slot->iv110.v110emu = 0;
-               }
-       }
        return __drv_command(drv, cmd);
 }
 
@@ -2057,27 +2035,18 @@ isdn_map_eaz2msn(char *msn, int di)
  * Find an unused ISDN-channel, whose feature-flags match the
  * given L2- and L3-protocols.
  */
-#define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038))
-
 int
 isdn_get_free_slot(int usage, int l2_proto, int l3_proto,
                   int pre_dev, int pre_chan, char *msn)
 {
        struct isdn_slot *slot;
        int i;
-       ulong flags;
-       ulong features;
-       ulong vfeatures;
+       unsigned long flags;
+       unsigned long features;
 
        save_flags(flags);
        cli();
        features = ((1 << l2_proto) | (0x10000 << l3_proto));
-       vfeatures = (((1 << l2_proto) | (0x10000 << l3_proto)) &
-                    ~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038));
-       /* If Layer-2 protocol is V.110, accept drivers with
-        * transparent feature even if these don't support V.110
-        * because we can emulate this in linklevel.
-        */
 
        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
                slot = &slots[i];
@@ -2097,16 +2066,15 @@ isdn_get_free_slot(int usage, int l2_proto, int l3_proto,
                if (strcmp(isdn_map_eaz2msn(msn, slot->di), "-") == 0)
                        continue;
 
-               if (((drivers[slot->di]->interface->features & features) == features) ||
-                   (((drivers[slot->di]->interface->features & vfeatures) == vfeatures) &&
-                            (drivers[slot->di]->interface->features & ISDN_FEATURE_L2_TRANS))) {
-                       if (pre_dev < 0 || pre_chan < 0 ||
-                           (pre_dev == slot->di && pre_chan == slot->ch)) {
-                               slot->usage = usage;
-                               isdn_info_update();
-                               fsm_event(&slot->fi, EV_SLOT_BIND, NULL);
-                               return i;
-                       }
+               if (!(drivers[slot->di]->features & features) == features)
+                       continue;
+
+               if (pre_dev < 0 || pre_chan < 0 ||
+                   (pre_dev == slot->di && pre_chan == slot->ch)) {
+                       slot->usage = usage;
+                       isdn_info_update();
+                       fsm_event(&slot->fi, EV_SLOT_BIND, NULL);
+                       return i;
                }
        }
        restore_flags(flags);
@@ -2137,70 +2105,11 @@ isdn_slot_free(int sl)
 int
 isdn_slot_write(int sl, struct sk_buff *skb)
 {
-       int ret;
-       struct sk_buff *nskb = NULL;
-       int v110_ret = skb->len;
+       struct isdn_slot *slot = &slots[sl];
 
        BUG_ON(sl < 0);
 
-       if (slots[sl].iv110.v110) {
-               atomic_inc(&slots[sl].iv110.v110use);
-               nskb = isdn_v110_encode(slots[sl].iv110.v110, skb);
-               atomic_dec(&slots[sl].iv110.v110use);
-               if (!nskb)
-                       return 0;
-               v110_ret = *((int *)nskb->data);
-               skb_pull(nskb, sizeof(int));
-               if (!nskb->len) {
-                       dev_kfree_skb(nskb);
-                       return v110_ret;
-               }
-               /* V.110 must always be acknowledged */
-               ret = fsm_event(&slots[sl].fi, EV_DATA_REQ, nskb);
-       } else {
-               int hl = isdn_slot_hdrlen(sl);
-
-               if( skb_headroom(skb) < hl ){
-                       /* 
-                        * This should only occur when new HL driver with
-                        * increased hl_hdrlen was loaded after netdevice
-                        * was created and connected to the new driver.
-                        *
-                        * The V.110 branch (re-allocates on its own) does
-                        * not need this
-                        */
-                       struct sk_buff * skb_tmp;
-
-                       skb_tmp = skb_realloc_headroom(skb, hl);
-                       printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed");
-                       if (!skb_tmp) return -ENOMEM; /* 0 better? */
-                       ret = fsm_event(&slots[sl].fi, EV_DATA_REQ, skb_tmp);
-                       if( ret > 0 ){
-                               dev_kfree_skb(skb);
-                       } else {
-                               dev_kfree_skb(skb_tmp);
-                       }
-               } else {
-                       ret = fsm_event(&slots[sl].fi, EV_DATA_REQ, skb);
-               }
-       }
-       if (ret > 0) {
-               slots[sl].obytes += ret;
-               if (slots[sl].iv110.v110) {
-                       atomic_inc(&slots[sl].iv110.v110use);
-                       slots[sl].iv110.v110->skbuser++;
-                       atomic_dec(&slots[sl].iv110.v110use);
-                       /* For V.110 return unencoded data length */
-                       ret = v110_ret;
-                       /* if the complete frame was send we free the skb;
-                          if not upper function will requeue the skb */ 
-                       if (ret == skb->len)
-                               dev_kfree_skb(skb);
-               }
-       } else
-               if (slots[sl].iv110.v110)
-                       dev_kfree_skb(nskb);
-       return ret;
+       return fsm_event(&slot->fi, EV_DATA_REQ, skb);
 }
 
 static int
@@ -2688,3 +2597,136 @@ static void __exit isdn_exit(void)
 
 module_init(isdn_init);
 module_exit(isdn_exit);
+
+static void
+isdn_v110_add_features(struct isdn_driver *drv)
+{
+       unsigned long features = drv->features >> ISDN_FEATURE_L2_SHIFT;
+
+       if (features & ISDN_FEATURE_L2_TRANS)
+               drv->features |= (ISDN_FEATURE_L2_V11096|
+                                 ISDN_FEATURE_L2_V11019|
+                                 ISDN_FEATURE_L2_V11038) << 
+                       ISDN_FEATURE_L2_SHIFT;
+}
+
+static void
+__isdn_v110_open(struct isdn_slot *slot)
+{
+       int sl = slot - slots;
+
+       if (!slot->iv110.v110emu)
+               return;
+
+       isdn_v110_open(sl, &slot->iv110);
+}
+
+static void
+__isdn_v110_close(struct isdn_slot *slot)
+{
+       int sl = slot - slots;
+
+       if (!slot->iv110.v110emu)
+               return;
+
+       isdn_v110_close(sl, &slot->iv110);
+}
+
+static void
+__isdn_v110_bsent(struct isdn_slot *slot, isdn_ctrl *c)
+{
+       int sl = slot - slots;
+
+       if (!slot->iv110.v110emu) {
+               do_stat_cb(slot, c);
+               return;
+       }
+       isdn_v110_bsent(sl, &slot->iv110);
+}
+
+/*
+ * Intercept command from Linklevel to Lowlevel.
+ * If layer 2 protocol is V.110 and this is not supported by current
+ * lowlevel-driver, use driver's transparent mode and handle V.110 in
+ * linklevel instead.
+ */
+static void
+isdn_v110_setl2(struct isdn_slot *slot, isdn_ctrl *cmd)
+{
+       struct isdn_driver *drv = slot->drv;
+
+       unsigned long l2prot = (cmd->arg >> 8) & 255;
+       unsigned long l2_feature = 1 << l2prot;
+       unsigned long features = drv->interface->features >> 
+               ISDN_FEATURE_L2_SHIFT;
+       
+       switch (l2prot) {
+       case ISDN_PROTO_L2_V11096:
+       case ISDN_PROTO_L2_V11019:
+       case ISDN_PROTO_L2_V11038:
+               /* If V.110 requested, but not supported by
+                * HL-driver, set emulator-flag and change
+                * Layer-2 to transparent
+                */
+               if (!(features & l2_feature)) {
+                       slot->iv110.v110emu = l2prot;
+                       cmd->arg = (cmd->arg & 255) |
+                               (ISDN_PROTO_L2_TRANS << 8);
+               } else
+                       slot->iv110.v110emu = 0;
+       }
+}
+
+static int
+isdn_v110_data_ind(struct isdn_slot *slot, struct sk_buff *skb)
+{
+       int sl = slot - slots;
+
+       if (!slot->iv110.v110emu)
+               goto recv;
+               
+       skb = isdn_v110_decode(slot->iv110.v110, skb);
+       if (!skb)
+               return 0;
+
+recv:
+       slot->recv_cb(sl, skb);
+       return 0;
+}
+
+static int
+isdn_v110_data_req(struct isdn_slot *slot, struct sk_buff *skb)
+{
+       int retval, v110_ret;
+       struct sk_buff *nskb = NULL;
+
+       if (!slot->iv110.v110emu)
+               return isdn_writebuf_skb(slot, skb);
+
+       atomic_inc(&slot->iv110.v110use);
+       nskb = isdn_v110_encode(slot->iv110.v110, skb);
+       atomic_dec(&slot->iv110.v110use);
+       if (!nskb)
+               return -ENOMEM;
+
+       v110_ret = *(int *)nskb->data;
+       skb_pull(nskb, sizeof(int));
+       if (!nskb->len) {
+               dev_kfree_skb(nskb);
+               return v110_ret;
+       }
+       
+       retval = isdn_writebuf_skb(slot, nskb);
+       if (retval <= 0) {
+               dev_kfree_skb(nskb);
+               return retval;
+       }
+       dev_kfree_skb(skb);
+
+       atomic_inc(&slot->iv110.v110use);
+       slots->iv110.v110->skbuser++;
+       atomic_dec(&slot->iv110.v110use);
+
+       /* For V.110 return unencoded data length */
+       return v110_ret;
+}
index 4a0ca7339f0a90c1c7e2cf36a794d4c92ff99c14..509e2a10951337bf3283fc6f80d4d4be2b85d77b 100644 (file)
@@ -2314,6 +2314,7 @@ isdn_tty_find_icall(int di, int ch, int sl, setup_parm *setup)
 static int
 isdn_tty_stat_callback(int i, isdn_ctrl *c)
 {
+       isdn_ctrl cmd;
        modem_info *info;
        char *e;
 
@@ -2366,6 +2367,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
 #endif
                                if (TTY_IS_ACTIVE(info)) {
                                        if (info->dialing == 1) {
+                                               isdn_slot_command(info->isdn_slot, ISDN_CMD_ACCEPTB, &cmd);
                                                info->dialing = 2;
                                                return 1;
                                        }
index 8d8ba2f04c523583d3a56775cc09bc0a1925fbf8..ed2d8f12abf8926163130b4cb59fb433ef16237e 100644 (file)
@@ -82,7 +82,7 @@ FlipBits(unsigned char c, int keylen)
  * structures and returns a pointer to these.
  */
 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;
        isdn_v110_stream *v;
@@ -127,8 +127,8 @@ isdn_v110_open(unsigned char key, int hdrlen, int maxsize)
 }
 
 /* isdn_v110_close frees private V.110 data structures */
-void
-isdn_v110_close(isdn_v110_stream * v)
+static void
+do_isdn_v110_close(isdn_v110_stream * v)
 {
        if (v == NULL)
                return;
@@ -510,99 +510,94 @@ buffer_full:
        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
-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;
-       int i;
-       int ret;
-
-       switch (c->command) {
-               case ISDN_STAT_BSENT:
-                        /* Keep the send-queue of the driver filled
-                        * with frames:
-                        * If number of outstanding frames < 3,
-                        * send down an Idle-Frame (or an Sync-Frame, if
-                        * v->SyncInit != 0). 
-                        */
-                       if (!(v = iv110->v110))
-                               return 0;
-                       atomic_inc(&iv110->v110use);
-                       if (v->skbidle > 0) {
-                               v->skbidle--;
-                               ret = 1;
+       isdn_v110_stream *v = iv110->v110;
+       int i, ret;
+
+       /* Keep the send-queue of the driver filled
+        * with frames:
+        * If number of outstanding frames < 3,
+        * send down an Idle-Frame (or an Sync-Frame, if
+        * v->SyncInit != 0). 
+        */
+       atomic_inc(&iv110->v110use);
+       if (v->skbidle > 0) {
+               v->skbidle--;
+               ret = 1;
+       } else {
+               if (v->skbuser > 0)
+                       v->skbuser--;
+               ret = 0;
+       }
+       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->skbuser > 0)
-                                       v->skbuser--;
-                               ret = 0;
-                       }
-                       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();
+                               if (v->SyncInit)
+                                       v->SyncInit--;
+                               v->skbidle++;
                        }
+               } else
                        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;
 }
index 035ee011b80dfcf937c9a53b59273bbbe674dfa7..77a9474811666f9f852610c5f6f06ce802912a5f 100644 (file)
@@ -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 int isdn_v110_stat_callback(int sl, struct isdn_v110 *v110, isdn_ctrl *);
-extern void isdn_v110_close(isdn_v110_stream * v);
+extern void isdn_v110_open(int sl, struct isdn_v110 *iv110);
+
+extern void isdn_v110_close(int sl, struct isdn_v110 *iv110);
+
+extern int  isdn_v110_bsent(int sl, struct isdn_v110 *iv110);
 
 #endif