/*---------------------------------------------------------------------------* * event handler, executes function and sets new state *---------------------------------------------------------------------------*/ void i4b_next_l2state(l2_softc_t *l2sc, int event) { int currstate, newstate; int (*savpostfsmfunc)(int) = NULL; /* check event number */ if(event > N_EVENTS) panic("i4b_l2fsm.c: event > N_EVENTS\n"); /* get current state and check it */ if((currstate = l2sc->Q921_state) > N_STATES) /* failsafe */ panic("i4b_l2fsm.c: currstate > N_STATES\n"); /* get new state and check it */ if((newstate = l2state_tab[event][currstate].newstate) > N_STATES) panic("i4b_l2fsm.c: newstate > N_STATES\n"); if(newstate != ST_SUBSET) { /* state function does NOT set new state */ NDBGL2(L2_F_MSG, "FSM event [%s]: [%s/%d => %s/%d]", l2event_text[event], l2state_text[currstate], currstate, l2state_text[newstate], newstate); } /* execute state transition function */ (*l2state_tab[event][currstate].func)(l2sc); if(newstate == ST_SUBSET) { /* state function DOES set new state */ NDBGL2(L2_F_MSG, "FSM S-event [%s]: [%s => %s]", l2event_text[event], l2state_text[currstate], l2state_text[l2sc->Q921_state]); } /* check for illegal new state */ if(newstate == ST_ILL) { newstate = currstate; NDBGL2(L2_F_ERR, "FSM illegal state, state = %s, event = %s!", l2state_text[currstate], l2event_text[event]); } /* check if state machine function has to set new state */ if(newstate != ST_SUBSET) l2sc->Q921_state = newstate; /* no, we set new state */ if(l2sc->postfsmfunc != NULL) { NDBGL2(L2_F_MSG, "FSM executing postfsmfunc!"); /* try to avoid an endless loop */ savpostfsmfunc = l2sc->postfsmfunc; l2sc->postfsmfunc = NULL; (*savpostfsmfunc)(l2sc->postfsmarg); } }
/*---------------------------------------------------------------------------* * got s or i frame, check if valid ack for last sent frame *---------------------------------------------------------------------------*/ void i4b_rxd_ack(l2_softc_t *l2sc, struct isdn_l3_driver *drv, int nr) { #ifdef NOTDEF NDBGL2(L2_ERROR, "N(R)=%d, UA=%d, V(R)=%d, V(S)=%d, V(A)=%d", nr, l2sc->ua_num, l2sc->vr, l2sc->vs, l2sc->va); #endif if(l2sc->ua_num != UA_EMPTY) { int s; s = splnet(); M128DEC(nr); if(l2sc->ua_num != nr) NDBGL2(L2_ERROR, "((N(R)-1)=%d) != (UA=%d) !!!", nr, l2sc->ua_num); i4b_Dfreembuf(l2sc->ua_frame); l2sc->ua_num = UA_EMPTY; splx(s); } }
/*---------------------------------------------------------------------------* * got s or i frame, check if valid ack for last sent frame *---------------------------------------------------------------------------*/ void i4b_rxd_ack(l2_softc_t *l2sc, int nr) { #ifdef NOTDEF NDBGL2(L2_ERROR, "N(R)=%d, UA=%d, V(R)=%d, V(S)=%d, V(A)=%d", nr, l2sc->ua_num, l2sc->vr, l2sc->vs, l2sc->va); #endif if(l2sc->ua_num != UA_EMPTY) { CRIT_VAR; CRIT_BEG; M128DEC(nr); if(l2sc->ua_num != nr) NDBGL2(L2_ERROR, "((N(R)-1)=%d) != (UA=%d) !!!", nr, l2sc->ua_num); i4b_Dfreembuf(l2sc->ua_frame); l2sc->ua_num = UA_EMPTY; CRIT_END; } }
/*---------------------------------------------------------------------------* * FSM state ST_TEI_ASGD event dl establish request *---------------------------------------------------------------------------*/ static void F_T01(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_T01 executing"); i4b_establish_data_link(l2sc); l2sc->l3initiated = 1; }
/*---------------------------------------------------------------------------* * FSM state ST_TEI_ASGD event rx'd DM *---------------------------------------------------------------------------*/ static void F_T10(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_T10 executing"); if(l2sc->rxd_PF) { l2sc->Q921_state = ST_TEI_ASGD; } else { #ifdef NOTDEF if(NOT able_to_etablish) { l2sc->Q921_state = ST_TEI_ASGD; return; } #endif i4b_establish_data_link(l2sc); l2sc->l3initiated = 1; l2sc->Q921_state = ST_AW_EST; } }
/*---------------------------------------------------------------------------* * FSM state ST_TEI_ASGD event dl release request *---------------------------------------------------------------------------*/ static void F_T13(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_T13 executing"); l2sc->postfsmarg = l2sc->unit; l2sc->postfsmfunc = DL_Rel_Cnf_A; }
/*---------------------------------------------------------------------------* * FSM state ST_MULTIFR event rx'd RNR *---------------------------------------------------------------------------*/ static void F_MF19(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_MF19 executing"); l2sc->peer_busy = 1; if(l2sc->rxd_CR == CR_CMD_FROM_NT) { if(l2sc->rxd_PF == 1) { i4b_enquiry_response(l2sc); } } else { if(l2sc->rxd_PF == 1) { i4b_mdl_error_ind(l2sc, "F_MF19", MDL_ERR_A); } } if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs)) { l2sc->va = l2sc->rxd_NR; i4b_T203_stop(l2sc); i4b_T200_restart(l2sc); l2sc->Q921_state = ST_MULTIFR; } else { i4b_nr_error_recovery(l2sc); l2sc->Q921_state = ST_AW_EST; } }
/*---------------------------------------------------------------------------* * check for v(a) <= n(r) <= v(s) * nr = receive sequence frame counter, va = acknowledge sequence frame * counter and vs = transmit sequence frame counter *---------------------------------------------------------------------------*/ int i4b_l2_nr_ok(int nr, int va, int vs) { if((va > nr) && ((nr != 0) || (va != 127))) { NDBGL2(L2_ERROR, "ERROR, va = %d, nr = %d, vs = %d [1]", va, nr, vs); return 0; /* fail */ } if((nr > vs) && ((vs != 0) || (nr != 127))) { NDBGL2(L2_ERROR, "ERROR, va = %d, nr = %d, vs = %d [2]", va, nr, vs); return 0; /* fail */ } return 1; /* good */ }
/*---------------------------------------------------------------------------* * FSM state ST_AW_EST event T200 expiry *---------------------------------------------------------------------------*/ static void F_AE11(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_AE11 executing"); if(l2sc->RC >= N200) { i4b_Dcleanifq(&l2sc->i_queue); i4b_mdl_error_ind(l2sc, "F_AE11", MDL_ERR_G); l2sc->postfsmarg = l2sc->unit; l2sc->postfsmfunc = DL_Rel_Ind_A; l2sc->Q921_state = ST_TEI_ASGD; } else { l2sc->RC++; i4b_tx_sabme(l2sc, P1); i4b_T200_start(l2sc); l2sc->Q921_state = ST_AW_EST; } }
/*---------------------------------------------------------------------------* * FSM state ST_AW_REL event rx'd DISC *---------------------------------------------------------------------------*/ static void F_AR08(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_AR08 executing"); MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_IDLE); i4b_tx_ua(l2sc, l2sc->rxd_PF); }
/*---------------------------------------------------------------------------* * FSM state ST_AW_REL event T200 expiry *---------------------------------------------------------------------------*/ static void F_AR11(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_AR11 executing"); if(l2sc->RC >= N200) { i4b_mdl_error_ind(l2sc, "F_AR11", MDL_ERR_H); l2sc->postfsmarg = l2sc->unit; l2sc->postfsmfunc = DL_Rel_Cnf_A; l2sc->Q921_state = ST_TEI_ASGD; } else { l2sc->RC++; i4b_tx_disc(l2sc, P1); i4b_T200_start(l2sc); l2sc->Q921_state = ST_AW_REL; } }
/*---------------------------------------------------------------------------* * FSM state ST_MULTIFR event rx'd SABME *---------------------------------------------------------------------------*/ static void F_MF07(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_MF07 executing"); i4b_clear_exception_conditions(l2sc); MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_ACTIVE); i4b_tx_ua(l2sc, l2sc->rxd_PF); i4b_mdl_error_ind(l2sc, "F_MF07", MDL_ERR_F); if(l2sc->vs != l2sc->va) { i4b_Dcleanifq(&l2sc->i_queue); l2sc->postfsmarg = l2sc->unit; l2sc->postfsmfunc = DL_Est_Ind_A; } i4b_T200_stop(l2sc); i4b_T203_start(l2sc); l2sc->vs = 0; l2sc->va = 0; l2sc->vr = 0; }
/*---------------------------------------------------------------------------* * FSM state ST_MULTIFR event dl data request *---------------------------------------------------------------------------*/ static void F_MF12(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_MF12 executing"); i4b_i_frame_queued_up(l2sc); }
/*---------------------------------------------------------------------------* * FSM state ST_TEI_ASGD event rx'd UA *---------------------------------------------------------------------------*/ static void F_T09(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_T09 executing"); i4b_mdl_error_ind(l2sc, "F_T09", MDL_ERR_C); i4b_mdl_error_ind(l2sc, "F_T09", MDL_ERR_D); }
/*---------------------------------------------------------------------------* * FSM state ST_TEI_ASGD event rx'd SABME *---------------------------------------------------------------------------*/ static void F_T07(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_T07 executing"); /* XXX */ #ifdef NOTDEF if(NOT able to establish) { i4b_tx_dm(l2sc, l2sc->rxd_PF); l2sc->Q921_state = ST_TEI_ASGD; return; } #endif i4b_clear_exception_conditions(l2sc); MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_ACTIVE); i4b_tx_ua(l2sc, l2sc->rxd_PF); l2sc->vs = 0; l2sc->va = 0; l2sc->vr = 0; l2sc->postfsmarg = l2sc->unit; l2sc->postfsmfunc = DL_Est_Ind_A; i4b_T203_start(l2sc); l2sc->Q921_state = ST_MULTIFR; }
/*---------------------------------------------------------------------------* * FSM state ST_MULTIFR event T203 expiry *---------------------------------------------------------------------------*/ static void F_MF14(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_MF14 executing"); i4b_transmit_enquire(l2sc); l2sc->RC = 0; }
/*---------------------------------------------------------------------------* * FSM state ST_AW_EST event dl establish request *---------------------------------------------------------------------------*/ static void F_AE01(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_AE01 executing"); i4b_Dcleanifq(&l2sc->i_queue); l2sc->l3initiated = 1; }
/*---------------------------------------------------------------------------* * Q.921 timer T202 timeout function *---------------------------------------------------------------------------*/ static void i4b_T202_timeout(l2_softc_t *l2sc) { NDBGL2(L2_T_ERR, "bri %d, N202 = %d", l2sc->drv->bri, l2sc->N202); if(--(l2sc->N202)) { (*l2sc->T202func)(l2sc); } }
/*---------------------------------------------------------------------------* * transmit DISC command *---------------------------------------------------------------------------*/ void i4b_tx_disc(l2_softc_t *l2sc, pbit_t pbit) { struct mbuf *m; l2sc->stat.tx_disc++; NDBGL2(L2_U_MSG, "tx DISC, tei = %d", l2sc->tei); m = i4b_build_u_frame(l2sc, CR_CMD_TO_NT, pbit, DISC); PH_Data_Req(l2sc->unit, m, MBUF_FREE); }
/*---------------------------------------------------------------------------* * transmit FRMR response *---------------------------------------------------------------------------*/ void i4b_tx_frmr(l2_softc_t *l2sc, fbit_t fbit) { struct mbuf *m; l2sc->stat.tx_frmr++; NDBGL2(L2_U_MSG, "tx FRMR, tei = %d", l2sc->tei); m = i4b_build_u_frame(l2sc, CR_RSP_TO_NT, fbit, FRMR); PH_Data_Req(l2sc->unit, m, MBUF_FREE); }
/*---------------------------------------------------------------------------* * FSM state ST_AW_REL event persistent deactivation *---------------------------------------------------------------------------*/ static void F_AR05(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_AR05 executing"); l2sc->postfsmarg = l2sc->unit; l2sc->postfsmfunc = DL_Rel_Cnf_A; i4b_T200_stop(l2sc); }
/*---------------------------------------------------------------------------* * FSM state ST_AW_EST event dl data request *---------------------------------------------------------------------------*/ static void F_AE12(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_AE12 executing"); if(l2sc->l3initiated == 0) { i4b_i_frame_queued_up(l2sc); } }
/*---------------------------------------------------------------------------* * Q.921 timer T200 start *---------------------------------------------------------------------------*/ void i4b_T200_start(l2_softc_t *l2sc) { if(l2sc->T200 == TIMER_ACTIVE) return; NDBGL2(L2_T_MSG, "bri %d", l2sc->drv->bri); l2sc->T200 = TIMER_ACTIVE; START_TIMER(l2sc->T200_callout, i4b_T200_timeout, l2sc, T200DEF); }
/*---------------------------------------------------------------------------* * FSM state ST_TIMREC event rx'd FRMR *---------------------------------------------------------------------------*/ static void F_TR20(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_TR20 executing"); i4b_mdl_error_ind(l2sc, "F_TR20", MDL_ERR_K); i4b_establish_data_link(l2sc); l2sc->l3initiated = 0; }
/*---------------------------------------------------------------------------* * routine INVOKE RETRANSMISSION (Q.921 03/93 page 84) *---------------------------------------------------------------------------*/ void i4b_invoke_retransmission(l2_softc_t *l2sc, int nr) { CRIT_VAR; CRIT_BEG; NDBGL2(L2_ERROR, "nr = %d", nr ); while(l2sc->vs != nr) { NDBGL2(L2_ERROR, "nr(%d) != vs(%d)", nr, l2sc->vs); M128DEC(l2sc->vs); /* XXXXXXXXXXXXXXXXX */ if((l2sc->ua_num != UA_EMPTY) && (l2sc->vs == l2sc->ua_num)) { if(_IF_QFULL(&l2sc->i_queue)) { NDBGL2(L2_ERROR, "ERROR, I-queue full!"); } else { IF_ENQUEUE(&l2sc->i_queue, l2sc->ua_frame); l2sc->ua_num = UA_EMPTY; } } else { NDBGL2(L2_ERROR, "ERROR, l2sc->vs = %d, l2sc->ua_num = %d ",l2sc->vs, l2sc->ua_num); } /* XXXXXXXXXXXXXXXXX */ i4b_i_frame_queued_up(l2sc); } CRIT_END; }
/*---------------------------------------------------------------------------* * FSM state ST_AW_REL event mdl remove request *---------------------------------------------------------------------------*/ static void F_AR06(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_AR06 executing"); l2sc->postfsmarg = l2sc->unit; l2sc->postfsmfunc = DL_Rel_Cnf_A; i4b_T200_stop(l2sc); /*XXX*/ i4b_mdl_assign_ind(l2sc); }
/*---------------------------------------------------------------------------* * i4b_print_l2var - print some l2softc vars *---------------------------------------------------------------------------*/ void i4b_print_l2var(l2_softc_t *l2sc) { NDBGL2(L2_ERROR, "unit%d V(R)=%d, V(S)=%d, V(A)=%d,ACKP=%d,PBSY=%d,OBSY=%d", l2sc->unit, l2sc->vr, l2sc->vs, l2sc->va, l2sc->ack_pend, l2sc->peer_busy, l2sc->own_busy); }
/*---------------------------------------------------------------------------* * FSM state ST_AW_EST event persistent deactivation *---------------------------------------------------------------------------*/ static void F_AE05(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_AE05 executing"); i4b_Dcleanifq(&l2sc->i_queue); l2sc->postfsmarg = l2sc->unit; l2sc->postfsmfunc = DL_Rel_Ind_A; i4b_T200_stop(l2sc); }
/*---------------------------------------------------------------------------* * FSM state ST_TIMREC event dl release request *---------------------------------------------------------------------------*/ static void F_TR13(l2_softc_t *l2sc) { NDBGL2(L2_F_MSG, "FSM function F_TR13 executing"); i4b_Dcleanifq(&l2sc->i_queue); l2sc->RC = 0; i4b_tx_disc(l2sc, P1); i4b_T200_restart(l2sc); }
/*---------------------------------------------------------------------------* * Q.921 timer T203 start *---------------------------------------------------------------------------*/ void i4b_T203_start(l2_softc_t *l2sc) { #if I4B_T203_ACTIVE if (l2sc->T203 == TIMER_ACTIVE) return; NDBGL2(L2_T_MSG, "bri %d", l2sc->bri); l2sc->T203 = TIMER_ACTIVE; START_TIMER(l2sc->T203_callout, i4b_T203_timeout, l2sc, T203DEF); #endif }