diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
commit | d6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch) | |
tree | e2be02f33984c48ec019c654051d27964e42c441 /drivers/isdn/hisax/callc.c | |
parent | 609d1e803baf519487233b765eb487f9ec227a18 (diff) |
Merge with 2.3.19.
Diffstat (limited to 'drivers/isdn/hisax/callc.c')
-rw-r--r-- | drivers/isdn/hisax/callc.c | 1408 |
1 files changed, 625 insertions, 783 deletions
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c index bf09acd20..ce0428a46 100644 --- a/drivers/isdn/hisax/callc.c +++ b/drivers/isdn/hisax/callc.c @@ -1,4 +1,4 @@ -/* $Id: callc.c,v 2.25 1999/01/02 11:17:20 keil Exp $ +/* $Id: callc.c,v 2.34 1999/08/25 20:02:34 werner Exp $ * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -11,6 +11,39 @@ * Fritz Elfert * * $Log: callc.c,v $ + * Revision 2.34 1999/08/25 20:02:34 werner + * Changed return values for stat_icall(w) from 3->4 and 4->5 because of conflicts + * with existing software definitions. (PtP incomplete called party number) + * + * Revision 2.33 1999/08/25 17:00:09 keil + * Make ISAR V32bis modem running + * Make LL->HL interface open for additional commands + * + * Revision 2.32 1999/08/22 20:27:01 calle + * backported changes from kernel 2.3.14: + * - several #include "config.h" gone, others come. + * - "struct device" changed to "struct net_device" in 2.3.14, added a + * define in isdn_compat.h for older kernel versions. + * + * Revision 2.31 1999/08/05 20:43:10 keil + * ISAR analog modem support + * + * Revision 2.30 1999/07/25 16:24:04 keil + * Fixed TEI now working again + * + * Revision 2.29 1999/07/13 21:05:41 werner + * Modified set_channel_limit to use new callback ISDN_STAT_DISCH. + * + * Revision 2.28 1999/07/09 08:30:02 keil + * cosmetics + * + * Revision 2.27 1999/07/05 23:51:38 werner + * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl + * hisaxctrl id 10 <nr. of chans 0-2> + * + * Revision 2.26 1999/07/01 08:11:21 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * * Revision 2.25 1999/01/02 11:17:20 keil * Changes for 2.2 * @@ -112,10 +145,15 @@ #include "../avmb1/capicmd.h" /* this should be moved in a common place */ #ifdef MODULE +#ifdef COMPAT_HAS_NEW_SYMTAB #define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module)) -#endif /* MODULE */ +#else +extern long mod_use_count_; +#define MOD_USE_COUNT mod_use_count_ +#endif /* COMPAT_HAS_NEW_SYMTAB */ +#endif /* MODULE */ -const char *lli_revision = "$Revision: 2.25 $"; +const char *lli_revision = "$Revision: 2.34 $"; extern struct IsdnCard cards[]; extern int nrcards; @@ -146,28 +184,7 @@ static int chancount = 0; /* Flags for remembering action done in lli */ -#define FLG_START_D 0 -#define FLG_ESTAB_D 1 -#define FLG_CALL_SEND 2 -#define FLG_CALL_REC 3 -#define FLG_CALL_ALERT 4 -#define FLG_START_B 5 -#define FLG_CONNECT_B 6 -#define FLG_LL_DCONN 7 -#define FLG_LL_BCONN 8 -#define FLG_DISC_SEND 9 -#define FLG_DISC_REC 10 -#define FLG_REL_REC 11 -#define FLG_DO_ALERT 12 -#define FLG_DO_HANGUP 13 -#define FLG_DO_CONNECT 14 -#define FLG_DO_ESTAB 15 -#define FLG_RESUME 16 - -/* - * Because of callback it's a good idea to delay the shutdown of the d-channel - */ -#define DREL_TIMER_VALUE 40000 +#define FLG_START_B 0 /* * Find card with given driverId @@ -192,7 +209,7 @@ discard_queue(struct sk_buff_head *q) int ret=0; while ((skb = skb_dequeue(q))) { - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); ret++; } return(ret); @@ -211,44 +228,40 @@ link_debug(struct Channel *chanp, int direction, char *fmt, ...) va_end(args); } - enum { - ST_NULL, /* 0 inactive */ - ST_OUT_WAIT_D, /* 1 outgoing, awaiting d-channel establishment */ - ST_IN_WAIT_D, /* 2 incoming, awaiting d-channel establishment */ - ST_OUT_DIAL, /* 3 outgoing, SETUP send; awaiting confirm */ - ST_IN_WAIT_LL, /* 4 incoming call received; wait for LL confirm */ - ST_IN_ALERT_SEND, /* 5 incoming call received; ALERT send */ - ST_IN_WAIT_CONN_ACK, /* 6 incoming CONNECT send; awaiting CONN_ACK */ - ST_WAIT_BCONN, /* 7 CONNECT/CONN_ACK received, awaiting b-channel prot. estbl. */ - ST_ACTIVE, /* 8 active, b channel prot. established */ - ST_WAIT_BRELEASE, /* 9 call clear. (initiator), awaiting b channel prot. rel. */ - ST_WAIT_BREL_DISC, /* 10 call clear. (receiver), DISCONNECT req. received */ - ST_WAIT_DCOMMAND, /* 11 call clear. (receiver), awaiting DCHANNEL message */ - ST_WAIT_DRELEASE, /* 12 DISCONNECT sent, awaiting RELEASE */ - ST_WAIT_D_REL_CNF, /* 13 RELEASE sent, awaiting RELEASE confirm */ - ST_WAIT_DSHUTDOWN, /* 14 awaiting d-channel shutdown */ + ST_NULL, /* 0 inactive */ + ST_OUT_DIAL, /* 1 outgoing, SETUP send; awaiting confirm */ + ST_IN_WAIT_LL, /* 2 incoming call received; wait for LL confirm */ + ST_IN_ALERT_SENT, /* 3 incoming call received; ALERT send */ + ST_IN_WAIT_CONN_ACK, /* 4 incoming CONNECT send; awaiting CONN_ACK */ + ST_WAIT_BCONN, /* 5 CONNECT/CONN_ACK received, awaiting b-channel prot. estbl. */ + ST_ACTIVE, /* 6 active, b channel prot. established */ + ST_WAIT_BRELEASE, /* 7 call clear. (initiator), awaiting b channel prot. rel. */ + ST_WAIT_BREL_DISC, /* 8 call clear. (receiver), DISCONNECT req. received */ + ST_WAIT_DCOMMAND, /* 9 call clear. (receiver), awaiting DCHANNEL message */ + ST_WAIT_DRELEASE, /* 10 DISCONNECT sent, awaiting RELEASE */ + ST_WAIT_D_REL_CNF, /* 11 RELEASE sent, awaiting RELEASE confirm */ + ST_IN_PROCEED_SEND, /* 12 incoming call, proceeding send */ }; - -#define STATE_COUNT (ST_WAIT_DSHUTDOWN +1) - -static char *strState[] = -{ - "ST_NULL", - "ST_OUT_WAIT_D", - "ST_IN_WAIT_D", - "ST_OUT_DIAL", - "ST_IN_WAIT_LL", - "ST_IN_ALERT_SEND", - "ST_IN_WAIT_CONN_ACK", - "ST_WAIT_BCONN", - "ST_ACTIVE", + + +#define STATE_COUNT (ST_IN_PROCEED_SEND + 1) + + static char *strState[] = + { + "ST_NULL", + "ST_OUT_DIAL", + "ST_IN_WAIT_LL", + "ST_IN_ALERT_SENT", + "ST_IN_WAIT_CONN_ACK", + "ST_WAIT_BCONN", + "ST_ACTIVE", "ST_WAIT_BRELEASE", "ST_WAIT_BREL_DISC", "ST_WAIT_DCOMMAND", "ST_WAIT_DRELEASE", "ST_WAIT_D_REL_CNF", - "ST_WAIT_DSHUTDOWN", + "ST_IN_PROCEED_SEND", }; enum { @@ -256,29 +269,28 @@ enum { EV_SETUP_CNF, /* 1 */ EV_ACCEPTB, /* 2 */ EV_DISCONNECT_IND, /* 3 */ - EV_RELEASE_CNF, /* 4 */ - EV_DLEST, /* 5 */ - EV_DLRL, /* 6 */ + EV_RELEASE, /* 4 */ + EV_LEASED, /* 5 */ + EV_LEASED_REL, /* 6 */ EV_SETUP_IND, /* 7 */ - EV_RELEASE_IND, /* 8 */ - EV_ACCEPTD, /* 9 */ - EV_SETUP_CMPL_IND, /* 10 */ - EV_BC_EST, /* 11 */ - EV_WRITEBUF, /* 12 */ - EV_ESTABLISH, /* 13 */ - EV_HANGUP, /* 14 */ - EV_BC_REL, /* 15 */ - EV_CINF, /* 16 */ - EV_SUSPEND, /* 17 */ - EV_RESUME, /* 18 */ - EV_SHUTDOWN_D, /* 19 */ - EV_NOSETUP_RSP, /* 20 */ - EV_SETUP_ERR, /* 21 */ - EV_CONNECT_ERR, /* 22 */ - EV_RELEASE_ERR, /* 23 */ + EV_ACCEPTD, /* 8 */ + EV_SETUP_CMPL_IND, /* 9 */ + EV_BC_EST, /* 10 */ + EV_WRITEBUF, /* 11 */ + EV_HANGUP, /* 12 */ + EV_BC_REL, /* 13 */ + EV_CINF, /* 14 */ + EV_SUSPEND, /* 15 */ + EV_RESUME, /* 16 */ + EV_NOSETUP_RSP, /* 17 */ + EV_SETUP_ERR, /* 18 */ + EV_CONNECT_ERR, /* 19 */ + EV_PROCEED, /* 20 */ + EV_ALERT, /* 21 */ + EV_REDIR, /* 22 */ }; -#define EVENT_COUNT (EV_RELEASE_ERR +1) +#define EVENT_COUNT (EV_REDIR + 1) static char *strEvent[] = { @@ -286,150 +298,152 @@ static char *strEvent[] = "EV_SETUP_CNF", "EV_ACCEPTB", "EV_DISCONNECT_IND", - "EV_RELEASE_CNF", - "EV_DLEST", - "EV_DLRL", + "EV_RELEASE", + "EV_LEASED", + "EV_LEASED_REL", "EV_SETUP_IND", - "EV_RELEASE_IND", "EV_ACCEPTD", "EV_SETUP_CMPL_IND", "EV_BC_EST", "EV_WRITEBUF", - "EV_ESTABLISH", "EV_HANGUP", "EV_BC_REL", "EV_CINF", "EV_SUSPEND", "EV_RESUME", - "EV_SHUTDOWN_D", "EV_NOSETUP_RSP", "EV_SETUP_ERR", "EV_CONNECT_ERR", - "EV_RELEASE_ERR", + "EV_PROCEED", + "EV_ALERT", + "EV_REDIR", }; + +static inline void +HL_LL(struct Channel *chanp, int command) +{ + isdn_ctrl ic; + + ic.driver = chanp->cs->myid; + ic.command = command; + ic.arg = chanp->chan; + chanp->cs->iif.statcallb(&ic); +} + static inline void -lli_deliver_cause(struct Channel *chanp, isdn_ctrl *ic) +lli_deliver_cause(struct Channel *chanp) { - if (chanp->proc->para.cause < 0) + isdn_ctrl ic; + + if (chanp->proc->para.cause == NO_CAUSE) return; - ic->driver = chanp->cs->myid; - ic->command = ISDN_STAT_CAUSE; - ic->arg = chanp->chan; + ic.driver = chanp->cs->myid; + ic.command = ISDN_STAT_CAUSE; + ic.arg = chanp->chan; if (chanp->cs->protocol == ISDN_PTYPE_EURO) - sprintf(ic->parm.num, "E%02X%02X", chanp->proc->para.loc & 0x7f, + sprintf(ic.parm.num, "E%02X%02X", chanp->proc->para.loc & 0x7f, chanp->proc->para.cause & 0x7f); else - sprintf(ic->parm.num, "%02X%02X", chanp->proc->para.loc & 0x7f, + sprintf(ic.parm.num, "%02X%02X", chanp->proc->para.loc & 0x7f, chanp->proc->para.cause & 0x7f); - chanp->cs->iif.statcallb(ic); + chanp->cs->iif.statcallb(&ic); } -static void -lli_d_established(struct FsmInst *fi, int event, void *arg) +static inline void +lli_close(struct FsmInst *fi) { - struct Channel *chanp = fi->userdata; - - test_and_set_bit(FLG_ESTAB_D, &chanp->Flags); - if (chanp->leased) { - isdn_ctrl ic; - int ret; + struct Channel *chanp = fi->userdata; - chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); - FsmChangeState(fi, ST_IN_WAIT_LL); - test_and_set_bit(FLG_CALL_REC, &chanp->Flags); - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_ICALL_LEASED"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_ICALL; - ic.arg = chanp->chan; - ic.parm.setup.si1 = 7; - ic.parm.setup.si2 = 0; - ic.parm.setup.plan = 0; - ic.parm.setup.screen = 0; - sprintf(ic.parm.setup.eazmsn,"%d", chanp->chan + 1); - sprintf(ic.parm.setup.phone,"LEASED%d", chanp->cs->myid); - ret = chanp->cs->iif.statcallb(&ic); - if (chanp->debug & 1) - link_debug(chanp, 1, "statcallb ret=%d", ret); - if (!ret) { - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); - FsmChangeState(fi, ST_NULL); - } - } else if (fi->state == ST_WAIT_DSHUTDOWN) - FsmChangeState(fi, ST_NULL); + FsmChangeState(fi, ST_NULL); + chanp->Flags = 0; + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); } -static void -lli_d_released(struct FsmInst *fi, int event, void *arg) + static void +lli_leased_in(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - - test_and_clear_bit(FLG_START_D, &chanp->Flags); + struct Channel *chanp = fi->userdata; + + isdn_ctrl ic; + int ret; + + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); + FsmChangeState(fi, ST_IN_WAIT_LL); + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_ICALL_LEASED"); + ic.driver = chanp->cs->myid; + ic.command = ((chanp->chan < 2) ? ISDN_STAT_ICALL : ISDN_STAT_ICALLW); + ic.arg = chanp->chan; + ic.parm.setup.si1 = 7; + ic.parm.setup.si2 = 0; + ic.parm.setup.plan = 0; + ic.parm.setup.screen = 0; + sprintf(ic.parm.setup.eazmsn,"%d", chanp->chan + 1); + sprintf(ic.parm.setup.phone,"LEASED%d", chanp->cs->myid); + ret = chanp->cs->iif.statcallb(&ic); + if (chanp->debug & 1) + link_debug(chanp, 1, "statcallb ret=%d", ret); + + if (!ret) { + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); + FsmChangeState(fi, ST_NULL); + } } + /* * Dial out */ static void +lli_init_bchan_out(struct FsmInst *fi, int event, void *arg) +{ + struct Channel *chanp = fi->userdata; + + FsmChangeState(fi, ST_WAIT_BCONN); + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_DCONN"); + HL_LL(chanp, ISDN_STAT_DCONN); + init_b_st(chanp, 0); + chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL); +} + +static void lli_prep_dialout(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - FsmChangeState(fi, ST_OUT_WAIT_D); FsmDelTimer(&chanp->drel_timer, 60); FsmDelTimer(&chanp->dial_timer, 73); chanp->l2_active_protocol = chanp->l2_protocol; chanp->incoming = 0; - if (test_bit(FLG_ESTAB_D, &chanp->Flags)) { - FsmEvent(fi, EV_DLEST, NULL); - } else { - chanp->Flags = 0; - if (EV_RESUME == event) - test_and_set_bit(FLG_RESUME, &chanp->Flags); - test_and_set_bit(FLG_START_D, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL); - } -} -static void -lli_do_dialout(struct FsmInst *fi, int event, void *arg) -{ - struct Channel *chanp = fi->userdata; - int ev; - - FsmChangeState(fi, ST_OUT_DIAL); - chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); - if (test_and_clear_bit(FLG_RESUME, &chanp->Flags)) - ev = CC_RESUME | REQUEST; - else - ev = CC_SETUP | REQUEST; - if (chanp->leased) { - FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL); - } else { - test_and_set_bit(FLG_ESTAB_D, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, ev, chanp); - test_and_set_bit(FLG_CALL_SEND, &chanp->Flags); - } + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); + if (chanp->leased) { + lli_init_bchan_out(fi, event, arg); + } else { + FsmChangeState(fi, ST_OUT_DIAL); + chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | REQUEST, chanp); + } } static void -lli_init_bchan_out(struct FsmInst *fi, int event, void *arg) +lli_resume(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - isdn_ctrl ic; - FsmChangeState(fi, ST_WAIT_BCONN); - test_and_set_bit(FLG_LL_DCONN, &chanp->Flags); - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_DCONN"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DCONN; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - init_b_st(chanp, 0); - test_and_set_bit(FLG_START_B, &chanp->Flags); - chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL); + FsmDelTimer(&chanp->drel_timer, 60); + FsmDelTimer(&chanp->dial_timer, 73); + chanp->l2_active_protocol = chanp->l2_protocol; + chanp->incoming = 0; + + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); + if (chanp->leased) { + lli_init_bchan_out(fi, event, arg); + } else { + FsmChangeState(fi, ST_OUT_DIAL); + chanp->d_st->lli.l4l3(chanp->d_st, CC_RESUME | REQUEST, chanp); + } } static void @@ -438,12 +452,15 @@ lli_go_active(struct FsmInst *fi, int event, void *arg) struct Channel *chanp = fi->userdata; isdn_ctrl ic; + FsmChangeState(fi, ST_ACTIVE); chanp->data_open = !0; - test_and_set_bit(FLG_CONNECT_B, &chanp->Flags); + if (chanp->bcs->conmsg) + strcpy(ic.parm.num, chanp->bcs->conmsg); + else + ic.parm.num[0] = 0; if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_BCONN"); - test_and_set_bit(FLG_LL_BCONN, &chanp->Flags); + link_debug(chanp, 0, "STAT_BCONN %s", ic.parm.num); ic.driver = chanp->cs->myid; ic.command = ISDN_STAT_BCONN; ic.arg = chanp->chan; @@ -451,6 +468,7 @@ lli_go_active(struct FsmInst *fi, int event, void *arg) chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) (long)chanp->chan); } + /* * RESUME */ @@ -458,27 +476,6 @@ lli_go_active(struct FsmInst *fi, int event, void *arg) /* incomming call */ static void -lli_start_dchan(struct FsmInst *fi, int event, void *arg) -{ - struct Channel *chanp = fi->userdata; - - FsmChangeState(fi, ST_IN_WAIT_D); - FsmDelTimer(&chanp->drel_timer, 61); - if (event == EV_ACCEPTD) - test_and_set_bit(FLG_DO_CONNECT, &chanp->Flags); - else if (event == EV_HANGUP) { - test_and_set_bit(FLG_DO_HANGUP, &chanp->Flags); -#ifdef ALERT_REJECT - test_and_set_bit(FLG_DO_ALERT, &chanp->Flags); -#endif - } - if (test_bit(FLG_ESTAB_D, &chanp->Flags)) { - FsmEvent(fi, EV_DLEST, NULL); - } else if (!test_and_set_bit(FLG_START_D, &chanp->Flags)) - chanp->d_st->lli.l4l3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL); -} - -static void lli_deliver_call(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; @@ -493,11 +490,11 @@ lli_deliver_call(struct FsmInst *fi, int event, void *arg) */ if (1) { /* for only one TEI */ FsmChangeState(fi, ST_IN_WAIT_LL); - test_and_set_bit(FLG_CALL_REC, &chanp->Flags); if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_ICALL"); + link_debug(chanp, 0, (chanp->chan < 2) ? "STAT_ICALL" : "STAT_ICALLW"); ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_ICALL; + ic.command = ((chanp->chan < 2) ? ISDN_STAT_ICALL : ISDN_STAT_ICALLW); + ic.arg = chanp->chan; /* * No need to return "unknown" for calls without OAD, @@ -507,118 +504,95 @@ lli_deliver_call(struct FsmInst *fi, int event, void *arg) ret = chanp->cs->iif.statcallb(&ic); if (chanp->debug & 1) link_debug(chanp, 1, "statcallb ret=%d", ret); + switch (ret) { - case 1: /* OK, anybody likes this call */ + case 1: /* OK, someone likes this call */ FsmDelTimer(&chanp->drel_timer, 61); - if (test_bit(FLG_ESTAB_D, &chanp->Flags)) { - FsmChangeState(fi, ST_IN_ALERT_SEND); - test_and_set_bit(FLG_CALL_ALERT, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); - } else { - test_and_set_bit(FLG_DO_ALERT, &chanp->Flags); - FsmChangeState(fi, ST_IN_WAIT_D); - test_and_set_bit(FLG_START_D, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, - DL_ESTABLISH | REQUEST, NULL); - } + FsmChangeState(fi, ST_IN_ALERT_SENT); + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); + break; + case 5: /* direct redirect */ + case 4: /* Proceeding desired */ + FsmDelTimer(&chanp->drel_timer, 61); + FsmChangeState(fi, ST_IN_PROCEED_SEND); + chanp->d_st->lli.l4l3(chanp->d_st, CC_PROCEED_SEND | REQUEST, chanp->proc); + if (ret == 5) + { chanp->setup = ic.parm.setup; + chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc); + } break; case 2: /* Rejecting Call */ - test_and_clear_bit(FLG_CALL_REC, &chanp->Flags); break; case 0: /* OK, nobody likes this call */ default: /* statcallb problems */ chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); FsmChangeState(fi, ST_NULL); - if (test_bit(FLG_ESTAB_D, &chanp->Flags) && - !test_bit(FLG_PTP, &chanp->d_st->l2.flag)) - FsmRestartTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 61); break; } } else { chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); - FsmChangeState(fi, ST_NULL); - if (test_bit(FLG_ESTAB_D, &chanp->Flags) && - !test_bit(FLG_PTP, &chanp->d_st->l2.flag)) - FsmRestartTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 62); } } static void -lli_establish_d(struct FsmInst *fi, int event, void *arg) +lli_send_dconnect(struct FsmInst *fi, int event, void *arg) { - /* This establish the D-channel for pending L3 messages - * without blocking the channel - */ struct Channel *chanp = fi->userdata; - test_and_set_bit(FLG_DO_ESTAB, &chanp->Flags); - FsmChangeState(fi, ST_IN_WAIT_D); - test_and_set_bit(FLG_START_D, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL); + FsmChangeState(fi, ST_IN_WAIT_CONN_ACK); + chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc); } static void -lli_do_action(struct FsmInst *fi, int event, void *arg) +lli_send_alert(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - test_and_set_bit(FLG_ESTAB_D, &chanp->Flags); - if (chanp->leased) { - FsmChangeState(fi, ST_IN_WAIT_CONN_ACK); - test_and_clear_bit(FLG_DO_ALERT, &chanp->Flags); - test_and_clear_bit(FLG_DO_CONNECT, &chanp->Flags); - FsmEvent(&chanp->fi, EV_SETUP_CMPL_IND, NULL); - } else if (test_and_clear_bit(FLG_DO_CONNECT, &chanp->Flags) && - !test_bit(FLG_DO_HANGUP, &chanp->Flags)) { - FsmChangeState(fi, ST_IN_WAIT_CONN_ACK); - test_and_clear_bit(FLG_DO_ALERT, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc); - } else if (test_and_clear_bit(FLG_DO_ALERT, &chanp->Flags)) { - if (test_bit(FLG_DO_HANGUP, &chanp->Flags)) - FsmRestartTimer(&chanp->drel_timer, 40, EV_HANGUP, NULL, 63); - FsmChangeState(fi, ST_IN_ALERT_SEND); - test_and_set_bit(FLG_CALL_ALERT, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); - } else if (test_and_clear_bit(FLG_DO_HANGUP, &chanp->Flags)) { - FsmChangeState(fi, ST_WAIT_DRELEASE); - chanp->proc->para.cause = 0x15; /* Call Rejected */ - chanp->d_st->lli.l4l3(chanp->d_st, CC_REJECT | REQUEST, chanp->proc); - test_and_set_bit(FLG_DISC_SEND, &chanp->Flags); - } + FsmChangeState(fi, ST_IN_ALERT_SENT); + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); } static void -lli_send_dconnect(struct FsmInst *fi, int event, void *arg) +lli_send_redir(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - FsmChangeState(fi, ST_IN_WAIT_CONN_ACK); - chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc); } static void lli_init_bchan_in(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - isdn_ctrl ic; FsmChangeState(fi, ST_WAIT_BCONN); - test_and_set_bit(FLG_LL_DCONN, &chanp->Flags); if (chanp->debug & 1) link_debug(chanp, 0, "STAT_DCONN"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DCONN; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); + HL_LL(chanp, ISDN_STAT_DCONN); chanp->l2_active_protocol = chanp->l2_protocol; chanp->incoming = !0; init_b_st(chanp, !0); - test_and_set_bit(FLG_START_B, &chanp->Flags); chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL); } +static void +lli_setup_rsp(struct FsmInst *fi, int event, void *arg) +{ + struct Channel *chanp = fi->userdata; + + if (chanp->leased) { + lli_init_bchan_in(fi, event, arg); + } else { + FsmChangeState(fi, ST_IN_WAIT_CONN_ACK); +#ifdef WANT_ALERT + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); +#endif + chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc); + } +} + /* Call suspend */ static void @@ -632,82 +606,52 @@ lli_suspend(struct FsmInst *fi, int event, void *arg) /* Call clearing */ static void -lli_cancel_call(struct FsmInst *fi, int event, void *arg) +lli_disconnect_req(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - isdn_ctrl ic; FsmChangeState(fi, ST_WAIT_DRELEASE); - if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_BHUP"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - if (test_and_clear_bit(FLG_START_B, &chanp->Flags)) - release_b_st(chanp); - chanp->proc->para.cause = 0x10; /* Normal Call Clearing */ + chanp->proc->para.cause = 0x10; /* Normal Call Clearing */ chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc); - test_and_set_bit(FLG_DISC_SEND, &chanp->Flags); } static void -lli_shutdown_d(struct FsmInst *fi, int event, void *arg) +lli_disconnect_reject(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; + struct Channel *chanp = fi->userdata; - FsmDelTimer(&chanp->drel_timer, 62); - if (test_bit(FLG_PTP, &chanp->d_st->l2.flag)) { - FsmChangeState(fi, ST_NULL); - } else { - if (!test_bit(FLG_TWO_DCHAN, &chanp->cs->HW_Flags)) { - if (chanp->chan) { - if (chanp->cs->channel[0].fi.state != ST_NULL) - return; - } else { - if (chanp->cs->channel[1].fi.state != ST_NULL) - return; - } - } - FsmChangeState(fi, ST_WAIT_DSHUTDOWN); - test_and_clear_bit(FLG_ESTAB_D, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL); - } + FsmChangeState(fi, ST_WAIT_DRELEASE); + chanp->proc->para.cause = 0x15; /* Call Rejected */ + chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc); } static void -lli_timeout_d(struct FsmInst *fi, int event, void *arg) +lli_dhup_close(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; - - test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags); - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_DHUP"); - lli_deliver_cause(chanp, &ic); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - FsmChangeState(fi, ST_NULL); - chanp->Flags = 0; - test_and_set_bit(FLG_ESTAB_D, &chanp->Flags); - if (!test_bit(FLG_PTP, &chanp->d_st->l2.flag)) - FsmAddTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 60); - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); + struct Channel *chanp = fi->userdata; + + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_DHUP"); + lli_deliver_cause(chanp); + HL_LL(chanp, ISDN_STAT_DHUP); + + lli_close(fi); } static void -lli_go_null(struct FsmInst *fi, int event, void *arg) +lli_reject_req(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - - FsmChangeState(fi, ST_NULL); - chanp->Flags = 0; - FsmDelTimer(&chanp->drel_timer, 63); - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); + struct Channel *chanp = fi->userdata; + +#ifndef ALERT_REJECT + chanp->proc->para.cause = 0x15; /* Call Rejected */ + chanp->d_st->lli.l4l3(chanp->d_st, CC_REJECT | REQUEST, chanp->proc); + lli_dhup_close(fi, event, arg); +#else + FsmRestartTimer(&chanp->drel_timer, 40, EV_HANGUP, NULL, 63); + FsmChangeState(fi, ST_IN_ALERT_SENT); + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); +#endif } static void @@ -717,30 +661,15 @@ lli_disconn_bchan(struct FsmInst *fi, int event, void *arg) chanp->data_open = 0; FsmChangeState(fi, ST_WAIT_BRELEASE); - test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags); chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); } static void -lli_send_d_disc(struct FsmInst *fi, int event, void *arg) +lli_start_disc(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; isdn_ctrl ic; - if (test_bit(FLG_DISC_REC, &chanp->Flags) || - test_bit(FLG_REL_REC, &chanp->Flags)) - return; - FsmChangeState(fi, ST_WAIT_DRELEASE); - if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_BHUP"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - if (test_and_clear_bit(FLG_START_B, &chanp->Flags)) - release_b_st(chanp); if (chanp->leased) { ic.command = ISDN_STAT_CAUSE; ic.arg = chanp->chan; @@ -748,43 +677,46 @@ lli_send_d_disc(struct FsmInst *fi, int event, void *arg) chanp->cs->iif.statcallb(&ic); if (chanp->debug & 1) link_debug(chanp, 0, "STAT_DHUP"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - FsmChangeState(fi, ST_WAIT_DSHUTDOWN); - test_and_clear_bit(FLG_ESTAB_D, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL); + HL_LL(chanp, ISDN_STAT_DHUP); + lli_close(fi); } else { - if (test_and_clear_bit(FLG_DO_HANGUP, &chanp->Flags)) - chanp->proc->para.cause = 0x15; /* Call Reject */ - else - chanp->proc->para.cause = 0x10; /* Normal Call Clearing */ - chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc); - test_and_set_bit(FLG_DISC_SEND, &chanp->Flags); + lli_disconnect_req(fi, event, arg); } } static void -lli_released_bchan(struct FsmInst *fi, int event, void *arg) +lli_rel_b_disc(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; + struct Channel *chanp = fi->userdata; + + release_b_st(chanp); + lli_start_disc(fi, event, arg); +} - FsmChangeState(fi, ST_WAIT_DCOMMAND); - chanp->data_open = 0; - if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_BHUP"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - release_b_st(chanp); - test_and_clear_bit(FLG_START_B, &chanp->Flags); +static void +lli_bhup_disc(struct FsmInst *fi, int event, void *arg) +{ + struct Channel *chanp = fi->userdata; + + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_BHUP"); + HL_LL(chanp, ISDN_STAT_BHUP); + + lli_rel_b_disc(fi, event, arg); } +static void +lli_bhup_rel_b(struct FsmInst *fi, int event, void *arg) +{ + struct Channel *chanp = fi->userdata; + + FsmChangeState(fi, ST_WAIT_DCOMMAND); + chanp->data_open = 0; + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_BHUP"); + HL_LL(chanp, ISDN_STAT_BHUP); + release_b_st(chanp); +} static void lli_release_bchan(struct FsmInst *fi, int event, void *arg) @@ -792,117 +724,74 @@ lli_release_bchan(struct FsmInst *fi, int event, void *arg) struct Channel *chanp = fi->userdata; chanp->data_open = 0; - test_and_set_bit(FLG_DISC_REC, &chanp->Flags); FsmChangeState(fi, ST_WAIT_BREL_DISC); - test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags); chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); } + static void -lli_received_d_rel(struct FsmInst *fi, int event, void *arg) +lli_rel_b_dhup(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; + struct Channel *chanp = fi->userdata; - chanp->data_open = 0; - FsmChangeState(fi, ST_NULL); - test_and_set_bit(FLG_REL_REC, &chanp->Flags); - if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) { - chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); - } - if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_BHUP"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - if (test_and_clear_bit(FLG_START_B, &chanp->Flags)) - release_b_st(chanp); - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_DHUP"); - lli_deliver_cause(chanp, &ic); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - test_and_clear_bit(FLG_DISC_SEND, &chanp->Flags); - test_and_clear_bit(FLG_CALL_REC, &chanp->Flags); - test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags); - test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags); - test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags); - lli_timeout_d(fi, event, arg); + release_b_st(chanp); + lli_dhup_close(fi, event, arg); } static void -lli_received_d_relcnf(struct FsmInst *fi, int event, void *arg) +lli_bhup_dhup(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; + struct Channel *chanp = fi->userdata; - chanp->data_open = 0; - FsmChangeState(fi, ST_NULL); - if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) { - chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); - } - if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_BHUP"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - if (test_and_clear_bit(FLG_START_B, &chanp->Flags)) - release_b_st(chanp); - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_DHUP"); - lli_deliver_cause(chanp, &ic); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - test_and_clear_bit(FLG_DISC_SEND, &chanp->Flags); - test_and_clear_bit(FLG_CALL_REC, &chanp->Flags); - test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags); - test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags); - test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags); - lli_timeout_d(fi, event, arg); + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_BHUP"); + HL_LL(chanp, ISDN_STAT_BHUP); + + lli_rel_b_dhup(fi, event, arg); } static void -lli_received_d_disc(struct FsmInst *fi, int event, void *arg) +lli_abort(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; + struct Channel *chanp = fi->userdata; - chanp->data_open = 0; - FsmChangeState(fi, ST_WAIT_D_REL_CNF); - test_and_set_bit(FLG_DISC_REC, &chanp->Flags); - if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_BHUP"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - if (test_and_clear_bit(FLG_START_B, &chanp->Flags)) - release_b_st(chanp); - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_DHUP"); - lli_deliver_cause(chanp, &ic); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags); - test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags); - test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, CC_RELEASE | REQUEST, chanp->proc); + chanp->data_open = 0; + chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); + + lli_bhup_dhup(fi, event, arg); +} + +static void +lli_release_req(struct FsmInst *fi, int event, void *arg) +{ + struct Channel *chanp = fi->userdata; + + FsmChangeState(fi, ST_WAIT_D_REL_CNF); + chanp->d_st->lli.l4l3(chanp->d_st, CC_RELEASE | REQUEST, chanp->proc); +} + +static void +lli_rel_b_release_req(struct FsmInst *fi, int event, void *arg) +{ + struct Channel *chanp = fi->userdata; + + release_b_st(chanp); + lli_release_req(fi, event, arg); +} + +static void +lli_bhup_release_req(struct FsmInst *fi, int event, void *arg) +{ + struct Channel *chanp = fi->userdata; + + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_BHUP"); + HL_LL(chanp, ISDN_STAT_BHUP); + + lli_rel_b_release_req(fi, event, arg); } + /* processing charge info */ static void lli_charge_info(struct FsmInst *fi, int event, void *arg) @@ -920,259 +809,150 @@ lli_charge_info(struct FsmInst *fi, int event, void *arg) /* error procedures */ static void -lli_no_dchan(struct FsmInst *fi, int event, void *arg) +lli_dchan_not_ready(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - isdn_ctrl ic; if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_NODCH"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_NODCH; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - chanp->Flags = 0; - FsmChangeState(fi, ST_NULL); - chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL); + link_debug(chanp, 0, "STAT_DHUP"); + HL_LL(chanp, ISDN_STAT_DHUP); } static void -lli_no_dchan_ready(struct FsmInst *fi, int event, void *arg) +lli_no_setup_rsp(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - isdn_ctrl ic; if (chanp->debug & 1) link_debug(chanp, 0, "STAT_DHUP"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); + HL_LL(chanp, ISDN_STAT_DHUP); + lli_close(fi); } static void -lli_no_dchan_in(struct FsmInst *fi, int event, void *arg) +lli_error(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; - - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_DHUP"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL | REQUEST, chanp->proc); - chanp->Flags = 0; - FsmChangeState(fi, ST_NULL); - chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL); + FsmChangeState(fi, ST_WAIT_DRELEASE); } static void -lli_no_setup_rsp(struct FsmInst *fi, int event, void *arg) +lli_failure_l(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; - - FsmChangeState(fi, ST_NULL); - test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags); - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_DHUP"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - lli_shutdown_d(fi, event, arg); + struct Channel *chanp = fi->userdata; + isdn_ctrl ic; + + FsmChangeState(fi, ST_NULL); + ic.driver = chanp->cs->myid; + ic.command = ISDN_STAT_CAUSE; + ic.arg = chanp->chan; + sprintf(ic.parm.num, "L%02X%02X", 0, 0x2f); + chanp->cs->iif.statcallb(&ic); + HL_LL(chanp, ISDN_STAT_DHUP); + chanp->Flags = 0; + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); } static void -lli_setup_err(struct FsmInst *fi, int event, void *arg) +lli_rel_b_fail(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; + struct Channel *chanp = fi->userdata; - FsmChangeState(fi, ST_WAIT_DRELEASE); - test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags); - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_DHUP"); - lli_deliver_cause(chanp, &ic); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - test_and_set_bit(FLG_DISC_SEND, &chanp->Flags); /* DISCONN was sent from L3 */ + release_b_st(chanp); + lli_failure_l(fi, event, arg); } static void -lli_connect_err(struct FsmInst *fi, int event, void *arg) +lli_bhup_fail(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; + struct Channel *chanp = fi->userdata; - FsmChangeState(fi, ST_WAIT_DRELEASE); - test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags); - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_DHUP"); - lli_deliver_cause(chanp, &ic); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - test_and_set_bit(FLG_DISC_SEND, &chanp->Flags); /* DISCONN was sent from L3 */ + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_BHUP"); + HL_LL(chanp, ISDN_STAT_BHUP); + + lli_rel_b_fail(fi, event, arg); } static void -lli_got_dlrl(struct FsmInst *fi, int event, void *arg) +lli_failure_a(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; + struct Channel *chanp = fi->userdata; - chanp->data_open = 0; - FsmChangeState(fi, ST_NULL); - if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) { - chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); - } - if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_BHUP"); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - if (test_and_clear_bit(FLG_START_B, &chanp->Flags)) - release_b_st(chanp); - if (chanp->leased) { - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_CAUSE; - ic.arg = chanp->chan; - sprintf(ic.parm.num, "L%02X%02X", 0, 0x2f); - chanp->cs->iif.statcallb(&ic); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - chanp->Flags = 0; - } else { - test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags); - if (chanp->debug & 1) - link_debug(chanp, 0, "STAT_DHUP"); - if (chanp->cs->protocol == ISDN_PTYPE_EURO) { - chanp->proc->para.cause = 0x2f; - chanp->proc->para.loc = 0; - } else { - chanp->proc->para.cause = 0x70; - chanp->proc->para.loc = 0; - } - lli_deliver_cause(chanp, &ic); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL | REQUEST, chanp->proc); - chanp->Flags = 0; - chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL); - } - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); -} - -/* *INDENT-OFF* */ -static struct FsmNode fnlist[] HISAX_INITDATA = -{ - {ST_NULL, EV_DIAL, lli_prep_dialout}, - {ST_NULL, EV_RESUME, lli_prep_dialout}, - {ST_NULL, EV_SETUP_IND, lli_deliver_call}, - {ST_NULL, EV_SHUTDOWN_D, lli_shutdown_d}, - {ST_NULL, EV_DLRL, lli_go_null}, - {ST_NULL, EV_DLEST, lli_d_established}, - {ST_NULL, EV_ESTABLISH, lli_establish_d}, - {ST_OUT_WAIT_D, EV_DLEST, lli_do_dialout}, - {ST_OUT_WAIT_D, EV_DLRL, lli_no_dchan}, - {ST_OUT_WAIT_D, EV_HANGUP, lli_no_dchan}, - {ST_IN_WAIT_D, EV_DLEST, lli_do_action}, - {ST_IN_WAIT_D, EV_DLRL, lli_no_dchan_in}, - {ST_IN_WAIT_D, EV_ACCEPTD, lli_start_dchan}, - {ST_IN_WAIT_D, EV_HANGUP, lli_start_dchan}, - {ST_OUT_DIAL, EV_SETUP_CNF, lli_init_bchan_out}, - {ST_OUT_DIAL, EV_HANGUP, lli_cancel_call}, - {ST_OUT_DIAL, EV_DISCONNECT_IND, lli_received_d_disc}, - {ST_OUT_DIAL, EV_RELEASE_IND, lli_received_d_rel}, - {ST_OUT_DIAL, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_OUT_DIAL, EV_NOSETUP_RSP, lli_no_setup_rsp}, - {ST_OUT_DIAL, EV_SETUP_ERR, lli_setup_err}, - {ST_OUT_DIAL, EV_DLRL, lli_got_dlrl}, - {ST_IN_WAIT_LL, EV_DLEST, lli_d_established}, - {ST_IN_WAIT_LL, EV_DLRL, lli_d_released}, - {ST_IN_WAIT_LL, EV_ACCEPTD, lli_start_dchan}, - {ST_IN_WAIT_LL, EV_HANGUP, lli_start_dchan}, - {ST_IN_WAIT_LL, EV_DISCONNECT_IND, lli_received_d_disc}, - {ST_IN_WAIT_LL, EV_RELEASE_IND, lli_received_d_rel}, - {ST_IN_WAIT_LL, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_IN_ALERT_SEND, EV_SETUP_CMPL_IND, lli_init_bchan_in}, - {ST_IN_ALERT_SEND, EV_ACCEPTD, lli_send_dconnect}, - {ST_IN_ALERT_SEND, EV_HANGUP, lli_send_d_disc}, - {ST_IN_ALERT_SEND, EV_DISCONNECT_IND, lli_received_d_disc}, - {ST_IN_ALERT_SEND, EV_RELEASE_IND, lli_received_d_rel}, - {ST_IN_ALERT_SEND, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_IN_ALERT_SEND, EV_DLRL, lli_got_dlrl}, - {ST_IN_WAIT_CONN_ACK, EV_SETUP_CMPL_IND, lli_init_bchan_in}, - {ST_IN_WAIT_CONN_ACK, EV_HANGUP, lli_send_d_disc}, - {ST_IN_WAIT_CONN_ACK, EV_DISCONNECT_IND, lli_received_d_disc}, - {ST_IN_WAIT_CONN_ACK, EV_RELEASE_IND, lli_received_d_rel}, - {ST_IN_WAIT_CONN_ACK, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_IN_WAIT_CONN_ACK, EV_CONNECT_ERR, lli_connect_err}, - {ST_IN_WAIT_CONN_ACK, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_BCONN, EV_BC_EST, lli_go_active}, - {ST_WAIT_BCONN, EV_BC_REL, lli_send_d_disc}, - {ST_WAIT_BCONN, EV_HANGUP, lli_send_d_disc}, - {ST_WAIT_BCONN, EV_DISCONNECT_IND, lli_received_d_disc}, - {ST_WAIT_BCONN, EV_RELEASE_IND, lli_received_d_rel}, - {ST_WAIT_BCONN, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_WAIT_BCONN, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_BCONN, EV_CINF, lli_charge_info}, - {ST_ACTIVE, EV_CINF, lli_charge_info}, - {ST_ACTIVE, EV_BC_REL, lli_released_bchan}, - {ST_ACTIVE, EV_SUSPEND, lli_suspend}, - {ST_ACTIVE, EV_HANGUP, lli_disconn_bchan}, - {ST_ACTIVE, EV_DISCONNECT_IND, lli_release_bchan}, - {ST_ACTIVE, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_ACTIVE, EV_RELEASE_IND, lli_received_d_rel}, - {ST_ACTIVE, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_BRELEASE, EV_BC_REL, lli_send_d_disc}, - {ST_WAIT_BRELEASE, EV_DISCONNECT_IND, lli_received_d_disc}, - {ST_WAIT_BRELEASE, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_WAIT_BRELEASE, EV_RELEASE_IND, lli_received_d_rel}, - {ST_WAIT_BRELEASE, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_BREL_DISC, EV_BC_REL, lli_received_d_disc}, - {ST_WAIT_BREL_DISC, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_WAIT_BREL_DISC, EV_RELEASE_IND, lli_received_d_rel}, - {ST_WAIT_BREL_DISC, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_DCOMMAND, EV_HANGUP, lli_send_d_disc}, - {ST_WAIT_DCOMMAND, EV_DISCONNECT_IND, lli_received_d_disc}, - {ST_WAIT_DCOMMAND, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_WAIT_DCOMMAND, EV_RELEASE_IND, lli_received_d_rel}, - {ST_WAIT_DCOMMAND, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_DRELEASE, EV_RELEASE_IND, lli_timeout_d}, - {ST_WAIT_DRELEASE, EV_RELEASE_CNF, lli_timeout_d}, - {ST_WAIT_DRELEASE, EV_RELEASE_ERR, lli_timeout_d}, - {ST_WAIT_DRELEASE, EV_DIAL, lli_no_dchan_ready}, - {ST_WAIT_DRELEASE, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_D_REL_CNF, EV_RELEASE_CNF, lli_timeout_d}, - {ST_WAIT_D_REL_CNF, EV_RELEASE_ERR, lli_timeout_d}, -/* ETS 300-104 16.1 */ - {ST_WAIT_D_REL_CNF, EV_RELEASE_IND, lli_timeout_d}, - {ST_WAIT_D_REL_CNF, EV_DIAL, lli_no_dchan_ready}, - {ST_WAIT_D_REL_CNF, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_DSHUTDOWN, EV_DLRL, lli_go_null}, - {ST_WAIT_DSHUTDOWN, EV_DLEST, lli_d_established}, - {ST_WAIT_DSHUTDOWN, EV_DIAL, lli_prep_dialout}, - {ST_WAIT_DSHUTDOWN, EV_RESUME, lli_prep_dialout}, - {ST_WAIT_DSHUTDOWN, EV_SETUP_IND, lli_deliver_call}, + chanp->data_open = 0; + chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); + + lli_bhup_fail(fi, event, arg); +} + + /* *INDENT-OFF* */ + static struct FsmNode fnlist[] HISAX_INITDATA = + { + {ST_NULL, EV_DIAL, lli_prep_dialout}, + {ST_NULL, EV_RESUME, lli_resume}, + {ST_NULL, EV_SETUP_IND, lli_deliver_call}, + {ST_NULL, EV_LEASED, lli_leased_in}, + {ST_OUT_DIAL, EV_SETUP_CNF, lli_init_bchan_out}, + {ST_OUT_DIAL, EV_HANGUP, lli_disconnect_req}, + {ST_OUT_DIAL, EV_DISCONNECT_IND, lli_release_req}, + {ST_OUT_DIAL, EV_RELEASE, lli_dhup_close}, + {ST_OUT_DIAL, EV_NOSETUP_RSP, lli_no_setup_rsp}, + {ST_OUT_DIAL, EV_SETUP_ERR, lli_error}, + {ST_IN_WAIT_LL, EV_LEASED_REL, lli_failure_l}, + {ST_IN_WAIT_LL, EV_ACCEPTD, lli_setup_rsp}, + {ST_IN_WAIT_LL, EV_HANGUP, lli_reject_req}, + {ST_IN_WAIT_LL, EV_DISCONNECT_IND, lli_release_req}, + {ST_IN_WAIT_LL, EV_RELEASE, lli_dhup_close}, + {ST_IN_ALERT_SENT, EV_SETUP_CMPL_IND, lli_init_bchan_in}, + {ST_IN_ALERT_SENT, EV_ACCEPTD, lli_send_dconnect}, + {ST_IN_ALERT_SENT, EV_HANGUP, lli_disconnect_reject}, + {ST_IN_ALERT_SENT, EV_DISCONNECT_IND, lli_release_req}, + {ST_IN_ALERT_SENT, EV_RELEASE, lli_dhup_close}, + {ST_IN_ALERT_SENT, EV_REDIR, lli_send_redir}, + {ST_IN_PROCEED_SEND, EV_REDIR, lli_send_redir}, + {ST_IN_PROCEED_SEND, EV_ALERT, lli_send_alert}, + {ST_IN_PROCEED_SEND, EV_ACCEPTD, lli_send_dconnect}, + {ST_IN_PROCEED_SEND, EV_HANGUP, lli_disconnect_reject}, + {ST_IN_PROCEED_SEND, EV_DISCONNECT_IND, lli_dhup_close}, + {ST_IN_ALERT_SENT, EV_RELEASE, lli_dhup_close}, + {ST_IN_WAIT_CONN_ACK, EV_SETUP_CMPL_IND, lli_init_bchan_in}, + {ST_IN_WAIT_CONN_ACK, EV_HANGUP, lli_disconnect_req}, + {ST_IN_WAIT_CONN_ACK, EV_DISCONNECT_IND, lli_release_req}, + {ST_IN_WAIT_CONN_ACK, EV_RELEASE, lli_dhup_close}, + {ST_IN_WAIT_CONN_ACK, EV_CONNECT_ERR, lli_error}, + {ST_WAIT_BCONN, EV_BC_EST, lli_go_active}, + {ST_WAIT_BCONN, EV_BC_REL, lli_rel_b_disc}, + {ST_WAIT_BCONN, EV_HANGUP, lli_rel_b_disc}, + {ST_WAIT_BCONN, EV_DISCONNECT_IND, lli_rel_b_release_req}, + {ST_WAIT_BCONN, EV_RELEASE, lli_rel_b_dhup}, + {ST_WAIT_BCONN, EV_LEASED_REL, lli_rel_b_fail}, + {ST_WAIT_BCONN, EV_CINF, lli_charge_info}, + {ST_ACTIVE, EV_CINF, lli_charge_info}, + {ST_ACTIVE, EV_BC_REL, lli_bhup_rel_b}, + {ST_ACTIVE, EV_SUSPEND, lli_suspend}, + {ST_ACTIVE, EV_HANGUP, lli_disconn_bchan}, + {ST_ACTIVE, EV_DISCONNECT_IND, lli_release_bchan}, + {ST_ACTIVE, EV_RELEASE, lli_abort}, + {ST_ACTIVE, EV_LEASED_REL, lli_failure_a}, + {ST_WAIT_BRELEASE, EV_BC_REL, lli_bhup_disc}, + {ST_WAIT_BRELEASE, EV_DISCONNECT_IND, lli_bhup_release_req}, + {ST_WAIT_BRELEASE, EV_RELEASE, lli_bhup_dhup}, + {ST_WAIT_BRELEASE, EV_LEASED_REL, lli_bhup_fail}, + {ST_WAIT_BREL_DISC, EV_BC_REL, lli_bhup_release_req}, + {ST_WAIT_BREL_DISC, EV_RELEASE, lli_bhup_dhup}, + {ST_WAIT_DCOMMAND, EV_HANGUP, lli_start_disc}, + {ST_WAIT_DCOMMAND, EV_DISCONNECT_IND, lli_release_req}, + {ST_WAIT_DCOMMAND, EV_RELEASE, lli_dhup_close}, + {ST_WAIT_DCOMMAND, EV_LEASED_REL, lli_failure_l}, + {ST_WAIT_DRELEASE, EV_RELEASE, lli_dhup_close}, + {ST_WAIT_DRELEASE, EV_DIAL, lli_dchan_not_ready}, + /* ETS 300-104 16.1 */ + {ST_WAIT_D_REL_CNF, EV_RELEASE, lli_dhup_close}, + {ST_WAIT_D_REL_CNF, EV_DIAL, lli_dchan_not_ready}, }; -/* *INDENT-ON* */ + /* *INDENT-ON* */ -#define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode)) + #define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode)) HISAX_INITFUNC(void CallcNew(void)) @@ -1195,21 +975,24 @@ release_b_st(struct Channel *chanp) { struct PStack *st = chanp->b_st; - chanp->bcs->BC_Close(chanp->bcs); - switch (chanp->l2_active_protocol) { - case (ISDN_PROTO_L2_X75I): - releasestack_isdnl2(st); - break; - case (ISDN_PROTO_L2_HDLC): - case (ISDN_PROTO_L2_TRANS): -// case (ISDN_PROTO_L2_MODEM): - releasestack_transl2(st); - break; - } + if(test_and_clear_bit(FLG_START_B, &chanp->Flags)) { + chanp->bcs->BC_Close(chanp->bcs); + switch (chanp->l2_active_protocol) { + case (ISDN_PROTO_L2_X75I): + releasestack_isdnl2(st); + break; + case (ISDN_PROTO_L2_HDLC): + case (ISDN_PROTO_L2_TRANS): + case (ISDN_PROTO_L2_MODEM): + case (ISDN_PROTO_L2_FAX): + releasestack_transl2(st); + break; + } + } } struct Channel -*selectfreechannel(struct PStack *st) +*selectfreechannel(struct PStack *st, int bch) { struct IsdnCardState *cs = st->l1.hardware; struct Channel *chanp = st->lli.userdata; @@ -1219,74 +1002,60 @@ struct Channel i=1; else i=0; - while (i<2) { + + if (!bch) + { i = 2; /* virtual channel */ + chanp += 2; + } + + while (i < ((bch) ? cs->chanlimit : (2 + MAX_WAITING_CALLS))) { if (chanp->fi.state == ST_NULL) return (chanp); chanp++; i++; } - return (NULL); -} - -int -is_activ(struct PStack *st) -{ - struct IsdnCardState *cs = st->l1.hardware; - struct Channel *chanp = st->lli.userdata; - int i; - if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags)) - i=1; - else - i=0; - while (i<2) { - if (test_bit(FLG_ESTAB_D, &chanp->Flags)) - return (1); + if (bch) /* number of channels is limited */ + { i = 2; /* virtual channel */ + chanp = st->lli.userdata; + chanp += i; + while (i < (2 + MAX_WAITING_CALLS)) { + if (chanp->fi.state == ST_NULL) + return (chanp); chanp++; i++; - } - return (0); + } + } + return (NULL); } +static void stat_redir_result(struct IsdnCardState *cs, int chan, ulong result) +{ isdn_ctrl ic; + + ic.driver = cs->myid; + ic.command = ISDN_STAT_REDIR; + ic.arg = chan; + (ulong)(ic.parm.num[0]) = result; + cs->iif.statcallb(&ic); +} /* stat_redir_result */ + static void dchan_l3l4(struct PStack *st, int pr, void *arg) { struct l3_process *pc = arg; - struct IsdnCardState *cs = st->l1.hardware; + struct IsdnCardState *cs = st->l1.hardware; struct Channel *chanp; - int event; - switch (pr) { - case (DL_ESTABLISH | INDICATION): - event = EV_DLEST; - break; - case (DL_RELEASE | INDICATION): - event = EV_DLRL; - break; - default: - event = -1; - break; - } - if (event >= 0) { - int i; - - chanp = st->lli.userdata; - if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags)) - i = 1; - else - i = 0; - while (i < 2) { - FsmEvent(&chanp->fi, event, NULL); - chanp++; - i++; - } - return; - } else if (pr == (CC_SETUP | INDICATION)) { - if (!(chanp = selectfreechannel(pc->st))) { - pc->st->lli.l4l3(pc->st, CC_DLRL | REQUEST, pc); - } else { - chanp->proc = pc; - pc->chan = chanp; + if(!pc) + return; + + if (pr == (CC_SETUP | INDICATION)) { + if (!(chanp = selectfreechannel(pc->st, pc->para.bchannel))) { + pc->para.cause = 0x11; /* User busy */ + pc->st->lli.l4l3(pc->st, CC_REJECT | REQUEST, pc); + } else { + chanp->proc = pc; + pc->chan = chanp; FsmEvent(&chanp->fi, EV_SETUP_IND, NULL); } return; @@ -1299,19 +1068,19 @@ dchan_l3l4(struct PStack *st, int pr, void *arg) FsmEvent(&chanp->fi, EV_DISCONNECT_IND, NULL); break; case (CC_RELEASE | CONFIRM): - FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL); + FsmEvent(&chanp->fi, EV_RELEASE, NULL); break; case (CC_SUSPEND | CONFIRM): - FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL); + FsmEvent(&chanp->fi, EV_RELEASE, NULL); break; case (CC_RESUME | CONFIRM): FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL); break; case (CC_RESUME_ERR): - FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL); + FsmEvent(&chanp->fi, EV_RELEASE, NULL); break; case (CC_RELEASE | INDICATION): - FsmEvent(&chanp->fi, EV_RELEASE_IND, NULL); + FsmEvent(&chanp->fi, EV_RELEASE, NULL); break; case (CC_SETUP_COMPL | INDICATION): FsmEvent(&chanp->fi, EV_SETUP_CMPL_IND, NULL); @@ -1332,15 +1101,21 @@ dchan_l3l4(struct PStack *st, int pr, void *arg) FsmEvent(&chanp->fi, EV_CONNECT_ERR, NULL); break; case (CC_RELEASE_ERR): - FsmEvent(&chanp->fi, EV_RELEASE_ERR, NULL); + FsmEvent(&chanp->fi, EV_RELEASE, NULL); break; + case (CC_PROCEED_SEND | INDICATION): case (CC_PROCEEDING | INDICATION): case (CC_ALERTING | INDICATION): + case (CC_PROGRESS | INDICATION): + case (CC_NOTIFY | INDICATION): break; + case (CC_REDIR | INDICATION): + stat_redir_result(cs, chanp->chan, pc->redir_result); + break; default: if (chanp->debug & 0x800) { HiSax_putstatus(chanp->cs, "Ch", - "%d L3->L4 unknown primitiv %x", + "%d L3->L4 unknown primitiv %#x", chanp->chan, pr); } } @@ -1406,6 +1181,7 @@ init_PStack(struct PStack **stp) { (*stp)->l2.l2l1 = dummy_pstack; (*stp)->l2.l2l3 = dummy_pstack; (*stp)->l3.l3l2 = dummy_pstack; + (*stp)->l3.l3ml3 = dummy_pstack; (*stp)->l3.l3l4 = dummy_pstack; (*stp)->lli.l4l3 = dummy_pstack; (*stp)->ma.layer = dummy_pstack; @@ -1446,14 +1222,19 @@ init_chan(int chan, struct IsdnCardState *csta) int CallcNewChan(struct IsdnCardState *csta) -{ +{ int i; + chancount += 2; init_chan(0, csta); init_chan(1, csta); printk(KERN_INFO "HiSax: 2 channels added\n"); + + for (i = 0; i < MAX_WAITING_CALLS; i++) + init_chan(i+2,csta); + printk(KERN_INFO "HiSax: MAX_WAITING_CALLS added\n"); + if (test_bit(FLG_PTP, &csta->channel->d_st->l2.flag)) { printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n"); - test_and_set_bit(FLG_START_D, &csta->channel->Flags); csta->channel->d_st->lli.l4l3(csta->channel->d_st, DL_ESTABLISH | REQUEST, NULL); } @@ -1482,14 +1263,13 @@ CallcFreeChan(struct IsdnCardState *csta) for (i = 0; i < 2; i++) { FsmDelTimer(&csta->channel[i].drel_timer, 74); FsmDelTimer(&csta->channel[i].dial_timer, 75); - if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) - release_d_st(csta->channel + i); - if (csta->channel[i].b_st) { - if (test_and_clear_bit(FLG_START_B, &csta->channel[i].Flags)) - release_b_st(csta->channel + i); - kfree(csta->channel[i].b_st); - csta->channel[i].b_st = NULL; - } else + if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) + release_d_st(csta->channel + i); + if (csta->channel[i].b_st) { + release_b_st(csta->channel + i); + kfree(csta->channel[i].b_st); + csta->channel[i].b_st = NULL; + } else printk(KERN_WARNING "CallcFreeChan b_st ch%d allready freed\n", i); if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) { release_d_st(csta->channel + i); @@ -1509,7 +1289,7 @@ lldata_handler(struct PStack *st, int pr, void *arg) if (chanp->data_open) chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb); else { - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); } break; case (DL_ESTABLISH | INDICATION): @@ -1521,7 +1301,7 @@ lldata_handler(struct PStack *st, int pr, void *arg) FsmEvent(&chanp->fi, EV_BC_REL, NULL); break; default: - printk(KERN_WARNING "lldata_handler unknown primitive %x\n", + printk(KERN_WARNING "lldata_handler unknown primitive %#x\n", pr); break; } @@ -1539,7 +1319,7 @@ lltrans_handler(struct PStack *st, int pr, void *arg) chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb); else { link_debug(chanp, 0, "channel not open"); - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); } break; case (PH_ACTIVATE | INDICATION): @@ -1551,7 +1331,7 @@ lltrans_handler(struct PStack *st, int pr, void *arg) FsmEvent(&chanp->fi, EV_BC_REL, NULL); break; default: - printk(KERN_WARNING "lltrans_handler unknown primitive %x\n", + printk(KERN_WARNING "lltrans_handler unknown primitive %#x\n", pr); break; } @@ -1566,7 +1346,7 @@ ll_writewakeup(struct PStack *st, int len) ic.driver = chanp->cs->myid; ic.command = ISDN_STAT_BSENT; ic.arg = chanp->chan; -// ic.parm.length = len; + ic.parm.length = len; chanp->cs->iif.statcallb(&ic); } @@ -1590,12 +1370,14 @@ init_b_st(struct Channel *chanp, int incoming) case (ISDN_PROTO_L2_TRANS): st->l1.mode = L1_MODE_TRANS; break; -#if 0 case (ISDN_PROTO_L2_MODEM): - st->l1.mode = L1_MODE_MODEM; + st->l1.mode = L1_MODE_V32; + break; + case (ISDN_PROTO_L2_FAX): + st->l1.mode = L1_MODE_FAX; break; -#endif } + chanp->bcs->conmsg = NULL; if (chanp->bcs->BC_SetStack(st, chanp->bcs)) return (-1); st->l2.flag = 0; @@ -1622,7 +1404,8 @@ init_b_st(struct Channel *chanp, int incoming) break; case (ISDN_PROTO_L2_HDLC): case (ISDN_PROTO_L2_TRANS): -// case (ISDN_PROTO_L2_MODEM): + case (ISDN_PROTO_L2_MODEM): + case (ISDN_PROTO_L2_FAX): st->l1.l1l2 = lltrans_handler; st->lli.userdata = chanp; st->lli.l1writewakeup = ll_writewakeup; @@ -1630,6 +1413,7 @@ init_b_st(struct Channel *chanp, int incoming) setstack_l3bc(st, chanp); break; } + test_and_set_bit(FLG_START_B, &chanp->Flags); return (0); } @@ -1642,7 +1426,7 @@ leased_l4l3(struct PStack *st, int pr, void *arg) switch (pr) { case (DL_DATA | REQUEST): link_debug(chanp, 0, "leased line d-channel DATA"); - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); break; case (DL_ESTABLISH | REQUEST): st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL); @@ -1650,7 +1434,7 @@ leased_l4l3(struct PStack *st, int pr, void *arg) case (DL_RELEASE | REQUEST): break; default: - printk(KERN_WARNING "transd_l4l3 unknown primitive %x\n", + printk(KERN_WARNING "transd_l4l3 unknown primitive %#x\n", pr); break; } @@ -1661,16 +1445,16 @@ leased_l1l2(struct PStack *st, int pr, void *arg) { struct Channel *chanp = (struct Channel *) st->lli.userdata; struct sk_buff *skb = arg; - int i,event = EV_DLRL; + int i,event = EV_LEASED_REL; switch (pr) { case (PH_DATA | INDICATION): link_debug(chanp, 0, "leased line d-channel DATA"); - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); break; case (PH_ACTIVATE | INDICATION): case (PH_ACTIVATE | CONFIRM): - event = EV_DLEST; + event = EV_LEASED; case (PH_DEACTIVATE | INDICATION): case (PH_DEACTIVATE | CONFIRM): if (test_bit(FLG_TWO_DCHAN, &chanp->cs->HW_Flags)) @@ -1685,7 +1469,7 @@ leased_l1l2(struct PStack *st, int pr, void *arg) break; default: printk(KERN_WARNING - "transd_l1l2 unknown primitive %x\n", pr); + "transd_l1l2 unknown primitive %#x\n", pr); break; } } @@ -1701,7 +1485,7 @@ distr_debug(struct IsdnCardState *csta, int debugflags) int i; struct Channel *chanp = csta->channel; - for (i = 0; i < 2; i++) { + for (i = 0; i < (2 + MAX_WAITING_CALLS) ; i++) { chanp[i].debug = debugflags; chanp[i].fi.debug = debugflags & 2; chanp[i].d_st->l2.l2m.debug = debugflags & 8; @@ -1774,14 +1558,43 @@ lli_got_manufacturer(struct Channel *chanp, struct IsdnCardState *cs, capi_msg * } } + +/***************************************************************/ +/* Limit the available number of channels for the current card */ +/***************************************************************/ +static int +set_channel_limit(struct IsdnCardState *cs, int chanmax) +{ + isdn_ctrl ic; + int i, ii; + + if ((chanmax < 0) || (chanmax > 2)) + return(-EINVAL); + cs->chanlimit = 0; + for (ii = 0; ii < 2; ii++) { + ic.driver = cs->myid; + ic.command = ISDN_STAT_DISCH; + ic.arg = ii; + if (ii >= chanmax) + ic.parm.num[0] = 0; /* disabled */ + else + ic.parm.num[0] = 1; /* enabled */ + i = cs->iif.statcallb(&ic); + if (i) return(-EINVAL); + if (ii < chanmax) + cs->chanlimit++; + } + return(0); +} /* set_channel_limit */ + int HiSax_command(isdn_ctrl * ic) { struct IsdnCardState *csta = hisax_findcard(ic->driver); + struct PStack *st; struct Channel *chanp; int i; u_int num; - u_long adr; if (!csta) { printk(KERN_ERR @@ -1789,12 +1602,10 @@ HiSax_command(isdn_ctrl * ic) ic->command, ic->driver); return -ENODEV; } - switch (ic->command) { case (ISDN_CMD_SETEAZ): chanp = csta->channel + ic->arg; break; - case (ISDN_CMD_SETL2): chanp = csta->channel + (ic->arg & 0xff); if (chanp->debug & 1) @@ -1868,7 +1679,7 @@ HiSax_command(isdn_ctrl * ic) HiSax_mod_inc_use_count(); #ifdef MODULE if (csta->channel[0].debug & 0x400) - HiSax_putstatus(csta, " LOCK ", "modcnt %x", + HiSax_putstatus(csta, " LOCK ", "modcnt %lx", MOD_USE_COUNT); #endif /* MODULE */ break; @@ -1876,7 +1687,7 @@ HiSax_command(isdn_ctrl * ic) HiSax_mod_dec_use_count(); #ifdef MODULE if (csta->channel[0].debug & 0x400) - HiSax_putstatus(csta, " UNLOCK ", "modcnt %x", + HiSax_putstatus(csta, " UNLOCK ", "modcnt %lx", MOD_USE_COUNT); #endif /* MODULE */ break; @@ -1949,8 +1760,6 @@ HiSax_command(isdn_ctrl * ic) HiSax_putstatus(csta, "set card ", "in PTP mode"); printk(KERN_DEBUG "HiSax: set card in PTP mode\n"); printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n"); - test_and_set_bit(FLG_START_D, &csta->channel[0].Flags); - test_and_set_bit(FLG_START_D, &csta->channel[1].Flags); csta->channel[0].d_st->lli.l4l3(csta->channel[0].d_st, DL_ESTABLISH | REQUEST, NULL); } else { @@ -1969,16 +1778,12 @@ HiSax_command(isdn_ctrl * ic) HiSax_putstatus(csta, "set card ", "in FIXED TEI (%d) mode", num); printk(KERN_DEBUG "HiSax: set card in FIXED TEI (%d) mode\n", num); - break; - case (9): /* load firmware */ - memcpy(&adr, ic->parm.num, sizeof(ulong)); - csta->cardmsg(csta, CARD_LOAD_FIRM, - (void *) adr); + chanp->d_st->lli.l4l3(chanp->d_st, + DL_ESTABLISH | REQUEST, NULL); break; #ifdef MODULE case (55): - while ( MOD_USE_COUNT > 0) - MOD_DEC_USE_COUNT; + MOD_USE_COUNT = 0; HiSax_mod_inc_use_count(); break; #endif /* MODULE */ @@ -2001,16 +1806,52 @@ HiSax_command(isdn_ctrl * ic) printk(KERN_DEBUG "HiSax: l3 debugging flags card %d set to %x\n", csta->cardnr + 1, *(unsigned int *) ic->parm.num); break; + case (10): + i = *(unsigned int *) ic->parm.num; + return(set_channel_limit(csta, i)); default: + if (csta->auxcmd) + return(csta->auxcmd(csta, ic)); printk(KERN_DEBUG "HiSax: invalid ioclt %d\n", (int) ic->arg); return (-EINVAL); } break; - default: + + case (ISDN_CMD_PROCEED): + chanp = csta->channel + ic->arg; + if (chanp->debug & 1) + link_debug(chanp, 1, "PROCEED"); + FsmEvent(&chanp->fi, EV_PROCEED, NULL); + break; + + case (ISDN_CMD_ALERT): + chanp = csta->channel + ic->arg; + if (chanp->debug & 1) + link_debug(chanp, 1, "ALERT"); + FsmEvent(&chanp->fi, EV_ALERT, NULL); break; - } + case (ISDN_CMD_REDIR): + chanp = csta->channel + ic->arg; + if (chanp->debug & 1) + link_debug(chanp, 1, "REDIR"); + chanp->setup = ic->parm.setup; + FsmEvent(&chanp->fi, EV_REDIR, NULL); + break; + + /* protocol specific io commands */ + case (ISDN_CMD_PROT_IO): + for (st = csta->stlist; st; st = st->next) + if (st->protocol == (ic->arg & 0xFF)) + return(st->lli.l4l3_proto(st, ic)); + return(-EINVAL); + break; + default: + if (csta->auxcmd) + return(csta->auxcmd(csta, ic)); + return(-EINVAL); + } return (0); } @@ -2049,7 +1890,8 @@ HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb) if (chanp->debug & 0x800) link_debug(chanp, 1, "writebuf: no buffers for %d bytes", len); return 0; - } + } else if (chanp->debug & 0x800) + link_debug(chanp, 1, "writebuf %d/%d/%d", len, chanp->bcs->tx_cnt,MAX_DATA_MEM); save_flags(flags); cli(); nskb = skb_clone(skb, GFP_ATOMIC); @@ -2062,7 +1904,7 @@ HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb) chanp->bcs->tx_cnt += len; st->l2.l2l1(st, PH_DATA | REQUEST, nskb); } - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_WRITE); } else len = 0; restore_flags(flags); |