2 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 *---------------------------------------------------------------------------
27 * i4b_l1fsm.c - isdn4bsd layer 1 I.430 state machine
28 * --------------------------------------------------
30 * $Id: isic_l1fsm.c,v 1.13 2007/10/19 11:59:54 ad Exp $
32 * last edit-date: [Fri Jan 5 11:36:11 2001]
34 *---------------------------------------------------------------------------*/
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: isic_l1fsm.c,v 1.12 2005/12/11 12:21:27 christos Exp $");
39 #include <sys/param.h>
40 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
41 #include <sys/ioccom.h>
43 #include <sys/ioctl.h>
45 #include <sys/kernel.h>
46 #include <sys/systm.h>
49 #include <machine/stdarg.h>
52 #include <machine/clock.h>
53 #include <i386/isa/isa_device.h>
58 #include <sys/device.h>
61 #include <sys/socket.h>
64 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
65 #include <sys/callout.h>
69 #include <machine/i4b_debug.h>
70 #include <machine/i4b_ioctl.h>
72 #include <netisdn/i4b_debug.h>
73 #include <netisdn/i4b_ioctl.h>
76 #include <netisdn/i4b_global.h>
77 #include <netisdn/i4b_trace.h>
78 #include <netisdn/i4b_l2.h>
79 #include <netisdn/i4b_l1l2.h>
80 #include <netisdn/i4b_mbuf.h>
82 #include <dev/ic/isic_l1.h>
83 #include <dev/ic/isac.h>
84 #include <dev/ic/hscx.h>
90 static const char *state_text
[N_STATES
] = {
93 "F5 Identifying Input",
100 static const char *event_text
[N_EVENTS
] = {
101 "EV_PHAR PH_ACT_REQ",
102 "EV_T3 Timer 3 expired",
103 "EV_INFO0 INFO0 received",
104 "EV_RSY Level Detected",
105 "EV_INFO2 INFO2 received",
106 "EV_INFO48 INFO4 received",
107 "EV_INFO410 INFO4 received",
108 "EV_DR Deactivate Req",
110 "EV_DIS Disconnected",
116 /* Function prototypes */
118 static void timer3_expired (struct isic_softc
*sc
);
119 static void T3_start (struct isic_softc
*sc
);
120 static void T3_stop (struct isic_softc
*sc
);
121 static void F_T3ex (struct isic_softc
*sc
);
122 static void timer4_expired (struct isic_softc
*sc
);
123 static void T4_start (struct isic_softc
*sc
);
124 static void T4_stop (struct isic_softc
*sc
);
125 static void F_AI8 (struct isic_softc
*sc
);
126 static void F_AI10 (struct isic_softc
*sc
);
127 static void F_I01 (struct isic_softc
*sc
);
128 static void F_I02 (struct isic_softc
*sc
);
129 static void F_I03 (struct isic_softc
*sc
);
130 static void F_I2 (struct isic_softc
*sc
);
131 static void F_ill (struct isic_softc
*sc
);
132 static void F_NULL (struct isic_softc
*sc
);
134 /*---------------------------------------------------------------------------*
135 * I.430 Timer T3 expire function
136 *---------------------------------------------------------------------------*/
138 timer3_expired(struct isic_softc
*sc
)
142 NDBGL1(L1_T_ERR
, "state = %s", isic_printstate(sc
));
145 /* XXX try some recovery here XXX */
146 switch(sc
->sc_cardtyp
) {
148 case CARD_TYPEP_AVMA1PCIV2
:
149 isic_isacsx_recover(sc
);
151 #endif /* NNISACSX > 0 */
155 #endif /* NNISAC > 0 */
159 sc
->sc_init_tries
++; /* increment retry count */
161 /*XXX*/ if(sc
->sc_init_tries
> 4)
165 sc
->sc_init_tries
= 0;
167 if(sc
->sc_obuf2
!= NULL
)
169 i4b_Dfreembuf(sc
->sc_obuf2
);
172 if(sc
->sc_obuf
!= NULL
)
174 i4b_Dfreembuf(sc
->sc_obuf
);
183 isdn_layer2_status_ind(&sc
->sc_l2
, sc
->sc_l3token
, STI_NOL1ACC
, 0);
186 isic_next_state(sc
, EV_T3
);
190 NDBGL1(L1_T_ERR
, "expired without starting it ....");
194 /*---------------------------------------------------------------------------*
195 * I.430 Timer T3 start
196 *---------------------------------------------------------------------------*/
198 T3_start(struct isic_softc
*sc
)
200 NDBGL1(L1_T_MSG
, "state = %s", isic_printstate(sc
));
203 START_TIMER(sc
->sc_T3_callout
, timer3_expired
, sc
, 2*hz
);
206 /*---------------------------------------------------------------------------*
207 * I.430 Timer T3 stop
208 *---------------------------------------------------------------------------*/
210 T3_stop(struct isic_softc
*sc
)
212 NDBGL1(L1_T_MSG
, "state = %s", isic_printstate(sc
));
214 sc
->sc_init_tries
= 0; /* init connect retry count */
219 STOP_TIMER(sc
->sc_T3_callout
, timer3_expired
, sc
);
223 /*---------------------------------------------------------------------------*
224 * I.430 Timer T3 expiry
225 *---------------------------------------------------------------------------*/
227 F_T3ex(struct isic_softc
*sc
)
229 NDBGL1(L1_F_MSG
, "FSM function F_T3ex executing");
230 if(((struct isdn_l3_driver
*)sc
->sc_l3token
)->protocol
!= PROTOCOL_D64S
)
231 isdn_layer2_activate_ind(&sc
->sc_l2
, sc
->sc_l3token
, 0);
234 /*---------------------------------------------------------------------------*
235 * Timer T4 expire function
236 *---------------------------------------------------------------------------*/
238 timer4_expired(struct isic_softc
*sc
)
242 NDBGL1(L1_T_MSG
, "state = %s", isic_printstate(sc
));
244 isdn_layer2_status_ind(&sc
->sc_l2
, sc
->sc_l3token
, STI_PDEACT
, 0);
248 NDBGL1(L1_T_ERR
, "expired without starting it ....");
252 /*---------------------------------------------------------------------------*
254 *---------------------------------------------------------------------------*/
256 T4_start(struct isic_softc
*sc
)
258 NDBGL1(L1_T_MSG
, "state = %s", isic_printstate(sc
));
261 START_TIMER(sc
->sc_T4_callout
, timer4_expired
, sc
, hz
);
264 /*---------------------------------------------------------------------------*
266 *---------------------------------------------------------------------------*/
268 T4_stop(struct isic_softc
*sc
)
270 NDBGL1(L1_T_MSG
, "state = %s", isic_printstate(sc
));
275 STOP_TIMER(sc
->sc_T4_callout
, timer4_expired
, sc
);
279 /*---------------------------------------------------------------------------*
280 * FSM function: received AI8
281 *---------------------------------------------------------------------------*/
283 F_AI8(struct isic_softc
*sc
)
287 NDBGL1(L1_F_MSG
, "FSM function F_AI8 executing");
289 if(((struct isdn_l3_driver
*)sc
->sc_l3token
)->protocol
!= PROTOCOL_D64S
)
290 isdn_layer2_activate_ind(&sc
->sc_l2
, sc
->sc_l3token
, 1);
294 if(sc
->sc_trace
& TRACE_I
)
302 isdn_layer2_trace_ind(&sc
->sc_l2
, sc
->sc_l3token
, &hdr
, 1, &info
);
306 /*---------------------------------------------------------------------------*
307 * FSM function: received AI10
308 *---------------------------------------------------------------------------*/
310 F_AI10(struct isic_softc
*sc
)
314 NDBGL1(L1_F_MSG
, "FSM function F_AI10 executing");
316 if(((struct isdn_l3_driver
*)sc
->sc_l3token
)->protocol
!= PROTOCOL_D64S
)
317 isdn_layer2_activate_ind(&sc
->sc_l2
, sc
->sc_l3token
, 1);
321 if(sc
->sc_trace
& TRACE_I
)
324 char info
= INFO4_10
;
329 isdn_layer2_trace_ind(&sc
->sc_l2
, sc
->sc_l3token
, &hdr
, 1, &info
);
333 /*---------------------------------------------------------------------------*
334 * FSM function: received INFO 0 in states F3 .. F5
335 *---------------------------------------------------------------------------*/
337 F_I01(struct isic_softc
*sc
)
339 NDBGL1(L1_F_MSG
, "FSM function F_I01 executing");
341 if(sc
->sc_trace
& TRACE_I
)
349 isdn_layer2_trace_ind(&sc
->sc_l2
, sc
->sc_l3token
, &hdr
, 1, &info
);
353 /*---------------------------------------------------------------------------*
354 * FSM function: received INFO 0 in state F6
355 *---------------------------------------------------------------------------*/
357 F_I02(struct isic_softc
*sc
)
359 NDBGL1(L1_F_MSG
, "FSM function F_I02 executing");
361 if(((struct isdn_l3_driver
*)sc
->sc_l3token
)->protocol
!= PROTOCOL_D64S
)
362 isdn_layer2_activate_ind(&sc
->sc_l2
, sc
->sc_l3token
, 0);
364 if(sc
->sc_trace
& TRACE_I
)
372 isdn_layer2_trace_ind(&sc
->sc_l2
, sc
->sc_l3token
, &hdr
, 1, &info
);
376 /*---------------------------------------------------------------------------*
377 * FSM function: received INFO 0 in state F7 or F8
378 *---------------------------------------------------------------------------*/
380 F_I03(struct isic_softc
*sc
)
382 NDBGL1(L1_F_MSG
, "FSM function F_I03 executing");
384 if(((struct isdn_l3_driver
*)sc
->sc_l3token
)->protocol
!= PROTOCOL_D64S
)
385 isdn_layer2_activate_ind(&sc
->sc_l2
, sc
->sc_l3token
, 0);
389 if(sc
->sc_trace
& TRACE_I
)
397 isdn_layer2_trace_ind(&sc
->sc_l2
, sc
->sc_l3token
, &hdr
, 1, &info
);
401 /*---------------------------------------------------------------------------*
402 * FSM function: activate request
403 *---------------------------------------------------------------------------*/
405 F_AR(struct isic_softc
*sc
)
407 NDBGL1(L1_F_MSG
, "FSM function F_AR executing");
409 if(sc
->sc_trace
& TRACE_I
)
417 isdn_layer2_trace_ind(&sc
->sc_l2
, sc
->sc_l3token
, &hdr
, 1, &info
);
420 switch(sc
->sc_cardtyp
) {
422 case CARD_TYPEP_AVMA1PCIV2
:
423 isic_isacsx_l1_cmd(sc
, CMD_AR8
);
425 #endif /* NNISACSX > 0 */
428 isic_isac_l1_cmd(sc
, CMD_AR8
);
429 #endif /* NNISAC > 0 */
436 /*---------------------------------------------------------------------------*
437 * FSM function: received INFO2
438 *---------------------------------------------------------------------------*/
440 F_I2(struct isic_softc
*sc
)
442 NDBGL1(L1_F_MSG
, "FSM function F_I2 executing");
444 if(sc
->sc_trace
& TRACE_I
)
452 isdn_layer2_trace_ind(&sc
->sc_l2
, sc
->sc_l3token
, &hdr
, 1, &info
);
456 /*---------------------------------------------------------------------------*
457 * illegal state default action
458 *---------------------------------------------------------------------------*/
460 F_ill(struct isic_softc
*sc
)
462 NDBGL1(L1_F_ERR
, "FSM function F_ill executing");
465 /*---------------------------------------------------------------------------*
467 *---------------------------------------------------------------------------*/
469 F_NULL(struct isic_softc
*sc
)
471 NDBGL1(L1_F_MSG
, "FSM function F_NULL executing");
475 /*---------------------------------------------------------------------------*
476 * layer 1 state transition table
477 *---------------------------------------------------------------------------*/
478 struct isic_state_tab
{
479 void (*func
) (struct isic_softc
*sc
); /* function to execute */
480 int newstate
; /* next state */
481 } isic_state_tab
[N_EVENTS
][N_STATES
] = {
483 /* STATE: F3 F4 F5 F6 F7 F8 ILLEGAL STATE */
484 /* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
485 /* EV_PHAR x*/ {{F_AR
, ST_F4
}, {F_NULL
, ST_F4
}, {F_NULL
, ST_F5
}, {F_NULL
, ST_F6
}, {F_ill
, ST_ILL
}, {F_NULL
, ST_F8
}, {F_ill
, ST_ILL
}},
486 /* EV_T3 x*/ {{F_NULL
, ST_F3
}, {F_T3ex
, ST_F3
}, {F_T3ex
, ST_F3
}, {F_T3ex
, ST_F3
}, {F_NULL
, ST_F7
}, {F_NULL
, ST_F8
}, {F_ill
, ST_ILL
}},
487 /* EV_INFO0 */ {{F_I01
, ST_F3
}, {F_I01
, ST_F4
}, {F_I01
, ST_F5
}, {F_I02
, ST_F3
}, {F_I03
, ST_F3
}, {F_I03
, ST_F3
}, {F_ill
, ST_ILL
}},
488 /* EV_RSY x*/ {{F_NULL
, ST_F3
}, {F_NULL
, ST_F5
}, {F_NULL
, ST_F5
}, {F_NULL
, ST_F8
}, {F_NULL
, ST_F8
}, {F_NULL
, ST_F8
}, {F_ill
, ST_ILL
}},
489 /* EV_INFO2 */ {{F_I2
, ST_F6
}, {F_I2
, ST_F6
}, {F_I2
, ST_F6
}, {F_I2
, ST_F6
}, {F_I2
, ST_F6
}, {F_I2
, ST_F6
}, {F_ill
, ST_ILL
}},
490 /* EV_INFO48*/ {{F_AI8
, ST_F7
}, {F_AI8
, ST_F7
}, {F_AI8
, ST_F7
}, {F_AI8
, ST_F7
}, {F_NULL
, ST_F7
}, {F_AI8
, ST_F7
}, {F_ill
, ST_ILL
}},
491 /* EV_INFO41*/ {{F_AI10
, ST_F7
}, {F_AI10
, ST_F7
}, {F_AI10
, ST_F7
}, {F_AI10
, ST_F7
}, {F_NULL
, ST_F7
}, {F_AI10
, ST_F7
}, {F_ill
, ST_ILL
}},
492 /* EV_DR */ {{F_NULL
, ST_F3
}, {F_NULL
, ST_F4
}, {F_NULL
, ST_F5
}, {F_NULL
, ST_F6
}, {F_NULL
, ST_F7
}, {F_NULL
, ST_F8
}, {F_ill
, ST_ILL
}},
493 /* EV_PU */ {{F_NULL
, ST_F3
}, {F_NULL
, ST_F4
}, {F_NULL
, ST_F5
}, {F_NULL
, ST_F6
}, {F_NULL
, ST_F7
}, {F_NULL
, ST_F8
}, {F_ill
, ST_ILL
}},
494 /* EV_DIS */ {{F_ill
, ST_ILL
}, {F_ill
, ST_ILL
}, {F_ill
, ST_ILL
}, {F_ill
, ST_ILL
}, {F_ill
, ST_ILL
}, {F_ill
, ST_ILL
}, {F_ill
, ST_ILL
}},
495 /* EV_EI */ {{F_NULL
, ST_F3
}, {F_NULL
, ST_F3
}, {F_NULL
, ST_F3
}, {F_NULL
, ST_F3
}, {F_NULL
, ST_F3
}, {F_NULL
, ST_F3
}, {F_ill
, ST_ILL
}},
496 /* EV_ILL */ {{F_ill
, ST_ILL
}, {F_ill
, ST_ILL
}, {F_ill
, ST_ILL
}, {F_ill
, ST_ILL
}, {F_ill
, ST_ILL
}, {F_ill
, ST_ILL
}, {F_ill
, ST_ILL
}}
499 /*---------------------------------------------------------------------------*
501 *---------------------------------------------------------------------------*/
503 isic_next_state(struct isic_softc
*sc
, int event
)
505 int currstate
, newstate
;
507 if(event
>= N_EVENTS
)
508 panic("i4b_l1fsm.c: event >= N_EVENTS");
510 currstate
= sc
->sc_I430state
;
512 if(currstate
>= N_STATES
)
513 panic("i4b_l1fsm.c: currstate >= N_STATES");
515 newstate
= isic_state_tab
[event
][currstate
].newstate
;
517 if(newstate
>= N_STATES
)
518 panic("i4b_l1fsm.c: newstate >= N_STATES");
520 NDBGL1(L1_F_MSG
, "FSM event [%s]: [%s => %s]", event_text
[event
],
521 state_text
[currstate
],
522 state_text
[newstate
]);
524 (*isic_state_tab
[event
][currstate
].func
)(sc
);
526 if(newstate
== ST_ILL
)
529 NDBGL1(L1_F_ERR
, "FSM Illegal State ERROR, oldstate = %s, newstate = %s, event = %s!",
530 state_text
[currstate
],
531 state_text
[newstate
],
535 sc
->sc_I430state
= newstate
;
539 /*---------------------------------------------------------------------------*
540 * return pointer to current state description
541 *---------------------------------------------------------------------------*/
543 isic_printstate(struct isic_softc
*sc
)
545 return(state_text
[sc
->sc_I430state
]);